2
* 3Depict.h - main program header
3
* Copyright (C) 2013 D Haley
5
* This program is free software: you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation, either version 3 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program. If not, see <http://www.gnu.org/licenses/>.
19
1
#include "mainFrame.h"
257
FILE_OPEN_TYPE_UNKNOWN=1,
258
FILE_OPEN_TYPE_XML=2,
259
FILE_OPEN_TYPE_POS=4,
260
FILE_OPEN_TYPE_TEXT=8
271
264
void setWxTreeImages(wxTreeCtrl *t, const map<size_t, wxArtID> &artFilters)
273
#if defined(__WIN32) || defined(__WIN64)
266
#if defined(__WIN32) || defined(__WIN64) || defined(__APPLE__)
274
267
const int winTreeIconSize=9;
275
268
wxImageList *imList = new wxImageList(winTreeIconSize,winTreeIconSize);
283
276
//Construct an image list for the tree
284
277
for(map<size_t,wxArtID>::const_iterator it=artFilters.begin();it!=artFilters.end();++it)
286
#if defined(__WIN32) || defined(__WIN64)
279
#if defined(__WIN32) || defined(__WIN64) || defined(__APPLE__)
288
281
imList->Add(wxBitmap(wxBitmap(wxArtProvider::GetBitmap(it->second)).
289
282
ConvertToImage().Rescale(winTreeIconSize, winTreeIconSize)));
354
347
fullscreenState=0;
355
348
verCheckThread=0;
356
349
lastMessageType=MESSAGE_NONE;
350
lastProgressData.reset();
357
352
//Set up the program icon handler
358
353
wxArtProvider::Push(new MyArtProvider);
359
354
SetIcon(wxArtProvider::GetIcon(wxT("MY_ART_ID_ICON")));
399
394
panelTop = new BasicGLPane(splitTopBottom);
403
397
#if wxCHECK_VERSION(2,9,0)
404
398
glPanelOK = panelTop->displaySupported();
406
400
#if defined(__WXGTK20__)
407
//I had to work this out by studying the constructor, and then testing simultaneously
401
//I had to work this out by studying the construtor, and then testing simultaneously
408
402
//on a broken and working Gl install. booyah.
409
403
glPanelOK=panelTop->m_glWidget;
410
404
#elif defined(__WIN32) || defined(__WIN64) || defined(__APPLE__)
621
615
bitmapFxStereoGlasses = new wxStaticBitmap(noteFxPanelStereo, wxID_ANY, wxNullBitmap);
622
616
labelFxStereoBaseline = new wxStaticText(noteFxPanelStereo, wxID_ANY, wxTRANS("Baseline Separation"));
623
617
sliderFxStereoBaseline = new wxSlider(noteFxPanelStereo,ID_EFFECT_STEREO_BASELINE_SLIDER, 20, 0, 100);
618
labelAppearance = new wxStaticText(noteTools, wxID_ANY, _("Appearance"));
624
619
checkAlphaBlend = new wxCheckBox(noteTools,ID_CHECK_ALPHA , wxTRANS("Smooth && translucent objects"));
625
620
checkAlphaBlend->SetValue(true);
626
621
checkLighting = new wxCheckBox(noteTools, ID_CHECK_LIGHTING, wxTRANS("3D lighting"));
627
622
checkLighting->SetValue(true);
623
static_line_1 = new wxStaticLine(noteTools, wxID_ANY);
624
labelPerformance = new wxStaticText(noteTools, wxID_ANY, wxTRANS("Performance"));
628
625
checkWeakRandom = new wxCheckBox(noteTools, ID_CHECK_WEAKRANDOM, wxTRANS("Fast and weak randomisation."));
629
626
checkWeakRandom->SetValue(true);
627
checkLimitOutput = new wxCheckBox(noteTools, ID_CHECK_LIMIT_POINT_OUT, wxTRANS("Limit Output Pts"));
628
checkLimitOutput->SetValue((visControl.getIonDisplayLimit() !=0));
630
stream_cast(tmpStr,visControl.getIonDisplayLimit());
631
textLimitOutput = new wxTextCtrl(noteTools, ID_TEXT_LIMIT_POINT_OUT, wxStr(tmpStr),
632
wxDefaultPosition,wxDefaultSize,wxTE_PROCESS_ENTER );
630
633
checkCaching = new wxCheckBox(noteTools, ID_CHECK_CACHING, wxTRANS("Filter caching"));
631
634
checkCaching->SetValue(true);
632
635
labelMaxRamUsage = new wxStaticText(noteTools, wxID_ANY, wxTRANS("Max. Ram usage (%)"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT);
765
768
//delete the file history pointer
766
769
delete recentHistory;
771
//Bindings did not get initialised, if glpane is not OK,
772
// so abort, rather than disconnecting
769
776
//wxwidgets can crash if objects are ->Connect-ed in
770
777
// wxWindowBase::DestroyChildren(), so Disconnect before destructing
870
877
EVT_CHECKBOX(ID_EFFECT_STEREO_LENSFLIP, MainWindowFrame::OnFxStereoLensFlip)
871
878
EVT_COMBOBOX(ID_EFFECT_STEREO_COMBO, MainWindowFrame::OnFxStereoCombo)
872
879
EVT_COMMAND_SCROLL(ID_EFFECT_STEREO_BASELINE_SLIDER, MainWindowFrame::OnFxStereoBaseline)
880
EVT_TEXT(ID_TEXT_LIMIT_POINT_OUT, MainWindowFrame::OnTextLimitOutput)
881
EVT_TEXT_ENTER(ID_TEXT_LIMIT_POINT_OUT, MainWindowFrame::OnTextLimitOutputEnter)
882
EVT_CHECKBOX(ID_CHECK_LIMIT_POINT_OUT, MainWindowFrame::OnCheckLimitOutput)
875
885
EVT_COMMAND(wxID_ANY, RemoteUpdateAvailEvent, MainWindowFrame::OnCheckUpdatesThread)
877
887
END_EVENT_TABLE();
890
unsigned int MainWindowFrame::guessFileType(const std::string &dataFile)
893
//Split the filename into chunks: path, volume, name and extension
894
//the format of this is OS dependant, but wxWidgets can deal with this.
896
wxString volume,path,name,ext;
898
fname.SplitPath(wxStr(dataFile),&volume,
899
&path,&name,&ext, &hasExt);
901
//Test the extension to determine what we will do
902
//TODO: This is really lazy, and I should use something like libmagic.
906
if( extStr == std::string("xml"))
907
return FILE_OPEN_TYPE_XML;
909
if( extStr == std::string("txt"))
910
return FILE_OPEN_TYPE_TEXT;
912
if( extStr == std::string("pos"))
913
return FILE_OPEN_TYPE_POS;
915
return FILE_OPEN_TYPE_UNKNOWN;
880
919
bool MainWindowFrame::getTreeFilterId(const wxTreeItemId &tId, size_t &filterId) const
934
void MainWindowFrame::checkAskSaveState()
937
if(visControl.hasStateData() && visControl.stateModifyLevel() >=STATE_MODIFIED_ANCILLARY)
939
wxMessageDialog *wxD =new wxMessageDialog(this,
940
wxTRANS("Current state has not been saved, would you like to save it now?")
941
,wxTRANS("State changed"),wxYES_NO|wxICON_QUESTION|wxYES_DEFAULT );
942
wxD->SetAffirmativeId(wxID_YES);
943
wxD->SetEscapeId(wxID_NO);
945
if ( wxD->ShowModal()== wxID_YES)
947
wxCommandEvent event;
896
953
void MainWindowFrame::OnFileOpen(wxCommandEvent &event)
899
956
if(currentlyUpdatingScene || visControl.isRefreshing())
902
962
//Load a file, either a state file, or a new pos file
903
963
wxFileDialog *wxF = new wxFileDialog(this,wxTRANS("Select Data or State File..."), wxT(""),
904
964
wxT(""),wxTRANS("Readable files (*.xml, *.pos, *.txt,*.csv)|*.xml;*.pos;*.txt;*.csv|POS File (*.pos)|*.pos|XML State File (*.xml)|*.xml|Text Data Files (*.txt/csv)|*.txt;*.csv|All Files (*)|*"),wxFD_OPEN|wxFD_FILE_MUST_EXIST);
907
967
if( (wxF->ShowModal() == wxID_CANCEL))
970
//See if the user would like to save state, if we are opening a state file
971
// which will overwrite our current state
972
std::string filePath = stlStr(wxF->GetPath());
973
if(guessFileType(filePath) == FILE_TYPE_XML)
910
978
textConsoleOut->Clear();
911
979
//Get vis controller to update tree control to match internal
912
980
// structure. Retain tree selection & visibility if we currently
1080
1150
bool MainWindowFrame::loadFile(const wxString &fileStr, bool merge)
1083
1152
//Don't try to alter viscontrol if we are refreshing. That would be bad.
1084
1153
ASSERT(!visControl.isRefreshing());
1085
1155
std::string dataFile = stlStr(fileStr);
1156
unsigned int fileType=guessFileType(dataFile);
1087
//Split the filename into chunks: path, volume, name and extension
1088
//the format of this is OS dependant, but wxWidgets can deal with this.
1090
wxString volume,path,name,ext;
1092
fname.SplitPath(fileStr,&volume,
1093
&path,&name,&ext, &hasExt);
1095
//Test the extension to determine what we will do
1096
//TODO: This is really lazy, and I should use something like libmagic.
1099
if( extStr == std::string("xml"))
1158
if(fileType == FILE_OPEN_TYPE_XML)
1101
1160
std::stringstream ss;
1120
//Try to restore the working directory as needed
1121
if(!(visControl.getWorkDir().size()))
1125
visControl.setWorkDir(stlStr(wd));
1129
if(wxDirExists(wxStr(visControl.getWorkDir())))
1130
wxSetWorkingDirectory(wxStr(visControl.getWorkDir()));
1135
1180
if(visControl.hasHazardousContents())
1153
1198
checkViewWorldAxis->Check(visControl.getAxisVisible());
1155
1201
//Update the camera dropdown
1156
vector<std::pair<unsigned int, std::string> > camData;
1157
visControl.getCamData(camData);
1202
vector<std::string > camNames;
1203
visControl.getCamData(camNames);
1159
1205
comboCamera->Clear();
1160
unsigned int uniqueID;
1161
//Skip the first element, as it is a hidden camera.
1162
for(unsigned int ui=1;ui<camData.size();ui++)
1206
for(unsigned int ui=1;ui<camNames.size();ui++)
1164
1208
//Do not delete as this will be deleted by wx
1165
comboCamera->Append(wxStr(camData[ui].second),
1166
(wxClientData *)new wxListUint(camData[ui].first));
1209
comboCamera->Append(wxStr(camNames[ui]),
1210
(wxClientData *)new wxListUint(ui));
1167
1211
//If this is the active cam (1) set the selection and (2) remember
1169
if(camData[ui].first == visControl.getActiveCamId())
1213
if(ui == visControl.getActiveCamId())
1171
1214
comboCamera->SetSelection(ui-1);
1172
uniqueID=camData[ui].first;
1176
1217
//Only update the camera grid if we have a valid uniqueID
1177
if(camData.size() > 1)
1218
if(camNames.size() > 1)
1179
1220
//Use the remembered ID to update the grid.
1180
visControl.updateCamPropertyGrid(gridCameraProperties,uniqueID);
1221
visControl.updateCamPropertyGrid(gridCameraProperties,
1222
visControl.getActiveCamId());
1228
1270
FilterTree fTree;
1230
Filter *posFilter,*downSampleFilter;
1231
1273
posFilter= configFile.getDefaultFilter(FILTER_TYPE_DATALOAD);
1232
downSampleFilter= configFile.getDefaultFilter(FILTER_TYPE_IONDOWNSAMPLE);
1234
1275
//Bastardise the default settings such that it knows to use the correct
1235
1276
// file type, based upon file extension
1236
1277
unsigned int fileMode;
1237
if(extStr == std::string("txt") || extStr == std::string("csv") )
1278
if(fileType == FILE_OPEN_TYPE_TEXT)
1238
1279
fileMode=DATALOAD_TEXT_FILE;
1240
1281
fileMode=DATALOAD_FLOAT_FILE;
1252
1293
//Append a new filter to the filter tree
1253
1294
fTree.addFilter(posFilter,0);
1254
fTree.addFilter(downSampleFilter,posFilter);
1255
1295
visControl.addFilterTree(fTree,true,0);
1257
currentFile.clear();
1260
1299
visControl.updateWxTreeCtrl(treeFilters);
1282
1321
if(getTreeFilterId(treeFilters->GetSelection(),filterId))
1283
1322
visControl.setWxTreeFilterViewPersistence(filterId);
1286
1324
bool loadOK=false;
1287
1325
if(!wxFileExists(f))
1288
1326
statusMessage("File does not exist",MESSAGE_ERROR);
1289
else if(loadFile(f))
1292
statusMessage(TRANS("Loaded file."),MESSAGE_INFO);
1293
panelTop->Refresh();
1329
//See if the user wants to save the current state
1330
if(guessFileType(stlStr(f)) == FILE_TYPE_XML)
1331
checkAskSaveState();
1336
statusMessage(TRANS("Loaded file."),MESSAGE_INFO);
1337
panelTop->Refresh();
1300
1345
recentHistory->RemoveFileFromHistory(event.GetId()-wxID_FILE1);
1301
1346
configFile.removeRecentFile(stlStr(f));
1306
1354
void MainWindowFrame::OnFileSave(wxCommandEvent &event)
1308
if(!currentFile.length())
1356
std::string saveFilename=visControl.getFilename();
1358
//Save menu should not be selectable if there is no file to save to.
1359
ASSERT(!saveFilename.empty());
1311
1360
//If the file does not exist, use saveas instead
1312
if(!wxFileExists(currentFile))
1361
if( saveFilename.empty() || !wxFileExists(wxStr(saveFilename)))
1314
1363
OnFileSaveAs(event);
1320
1367
std::map<string,string> dummyMap;
1321
std::string dataFile = stlStr(currentFile);
1323
1368
//Try to save the viscontrol state
1324
if(!visControl.saveState(dataFile.c_str(),dummyMap))
1369
if(!visControl.saveState(saveFilename.c_str(),dummyMap))
1326
1371
wxErrMsg(this,TRANS("Save error"),TRANS("Unable to save. Check output destination can be written to."));
1330
fileSave->Enable(true);
1332
1375
//Update the recent files, and the menu.
1333
configFile.addRecentFile(dataFile);
1334
recentHistory->AddFileToHistory(wxStr(dataFile));
1336
dataFile=std::string("Saved state: ") + dataFile;
1337
statusMessage(dataFile.c_str(),MESSAGE_INFO);
1376
configFile.addRecentFile(saveFilename);
1377
recentHistory->AddFileToHistory(wxStr(saveFilename));
1380
tmpStr= std::string("Saved state: ") + saveFilename;
1381
statusMessage(tmpStr.c_str(),MESSAGE_INFO);
1343
1388
void MainWindowFrame::OnFileExportPlot(wxCommandEvent &event)
1621
1666
checkWeakRandom->Enable(!locking);
1622
1667
checkCaching->Enable(!locking);
1623
1668
spinCachePercent->Enable(!locking);
1669
textLimitOutput->Enable(!locking);
1670
checkLimitOutput->Enable(!locking);
1625
1672
fileMenu->Enable(ID_FILE_OPEN,!locking);
1626
1673
fileMenu->Enable(ID_FILE_MERGE,!locking);
1627
fileMenu->Enable(ID_FILE_SAVE,!locking);
1675
//Save menu needs to be handled specially in the case of an unlock
1676
// as determining if it can be enabled needs work
1678
fileMenu->Enable(ID_FILE_SAVE,false);
1628
1682
fileMenu->Enable(ID_FILE_SAVEAS,!locking);
1630
1684
for(size_t ui=0;ui<recentFilesMenu->GetMenuItemCount();ui++)
1658
1712
fileMenu->Enable(ID_FILE_OPEN,!locking);
1659
1713
fileMenu->Enable(ID_FILE_MERGE,!locking);
1660
fileMenu->Enable(ID_FILE_SAVE,!locking);
1661
1714
fileMenu->Enable(ID_FILE_SAVEAS,!locking);
1716
//Save menu needs to be handled specially in the case of an unlock
1717
// as determining if it can be enabled needs work
1719
fileMenu->Enable(ID_FILE_SAVE,false);
1723
//Lock/unlock all the recent files entries
1663
1724
for(size_t ui=0;ui<recentFilesMenu->GetMenuItemCount();ui++)
1675
1736
//Locking of the tools pane
1676
1737
checkWeakRandom->Enable(!locking);
1677
1738
checkCaching->Enable(!locking);
1739
checkLimitOutput->Enable(!locking);
1740
textLimitOutput->Enable(!locking);
1678
1741
spinCachePercent->Enable(!locking);
1680
1744
//Lock panel spectra, so we cannot alter things like ranges
1681
1745
panelSpectra->limitInteraction(locking);
1787
1851
if(exportDialog->wantsImages())
1853
vector<SelectionDevice *> dummy;
1789
1854
//update the output streams, but do not release
1790
1855
// the contents.
1791
if(visControl.doUpdateScene(outStreams,false))
1856
if(visControl.doUpdateScene(outStreams,dummy,false))
1793
1858
pair<string,string> errMsg;
2287
currentFile = wxF->GetPath();
2288
fileSave->Enable(true);
2353
tmpStr=stlStr(wxF->GetPath());
2354
visControl.setFilename(tmpStr);
2290
2356
//Update the recent files, and the menu.
2291
2357
configFile.addRecentFile(dataFile);
3333
3401
//refresh the camera property grid
3334
3402
visControl.updateCamPropertyGrid(gridCameraProperties ,l->value);
3336
3406
//force redraw in 3D pane
3337
3407
panelTop->Refresh(false);
3522
3597
progressTimer->Start(PROGRESS_TIMER_DELAY);
3523
3598
currentlyUpdatingScene=true;
3524
3599
haveAborted=false;
3600
panelTop->currentScene.setShowProgress(true);
3527
3603
statusMessage("",MESSAGE_NONE);
3693
3772
//Save to the autosave file
3695
3774
s= stlStr(filePath);
3696
std::map<string,string> dummyMap;
3697
if(visControl.saveState(s.c_str(),dummyMap))
3698
statusMessage(TRANS("Autosave complete."),MESSAGE_INFO);
3776
//Only save if we have autosave data
3777
if(visControl.hasStateData())
3701
//The save failed, but may have left an incomplete file lying around
3702
if(wxFileExists(filePath))
3703
wxRemoveFile(filePath);
3779
std::map<string,string> dummyMap;
3780
if(visControl.saveState(s.c_str(),dummyMap,false,false))
3781
statusMessage(TRANS("Autosave complete."),MESSAGE_INFO);
3784
//The save failed, but may have left an incomplete file lying around
3785
if(wxFileExists(filePath))
3786
wxRemoveFile(filePath);
3944
//Check for new progress data
3857
3945
ProgressData p;
3858
3946
p=visControl.getProgress();
3948
if(p == lastProgressData)
3953
//Update the text progress
3859
3955
ASSERT(p.totalProgress <= visControl.numFilters());
3861
3957
if(p.filterProgress > 100)
3896
3992
progressString = totalProg + TRANS(" of ") + totalCount;
3899
3996
if( p.filterProgress != 100)
3900
3997
filterProg+=TRANS("\% Done (Esc aborts)");
3902
3999
filterProg+=TRANS("\% Done");
4002
//Update the scene progress icon
4003
if(panelTop->currentScene.getShowProgress())
4006
wxPostEvent(panelTop,wxP);
3907
4013
MainFrame_statusbar->SetStatusText(wxT(""),0);
3908
4014
MainFrame_statusbar->SetStatusText(wxStr(progressString),1);
3909
4015
MainFrame_statusbar->SetStatusText(wxStr(filterProg),2);
3912
4019
void MainWindowFrame::updatePostEffects()
4516
4627
doSceneUpdate();
4630
void MainWindowFrame::OnCheckLimitOutput(wxCommandEvent &event)
4633
if(event.IsChecked())
4635
bool isOK=validateTextAsStream(textLimitOutput,limitVal);
4643
visControl.setIonDisplayLimit(limitVal);
4646
configFile.setMaxPoints(limitVal);
4649
void MainWindowFrame::OnTextLimitOutput(wxCommandEvent &event)
4652
bool isOK=validateTextAsStream(textLimitOutput,limitVal);
4657
if(checkLimitOutput->IsChecked())
4659
visControl.setIonDisplayLimit(limitVal);
4660
configFile.setMaxPoints(limitVal);
4664
void MainWindowFrame::OnTextLimitOutputEnter(wxCommandEvent &event)
4667
bool isOK=validateTextAsStream(textLimitOutput,limitVal);
4672
if(checkLimitOutput->IsChecked())
4674
visControl.setIonDisplayLimit(limitVal);
4678
//If we set the limit to zero this is a special case
4679
// that disables the limit, so untick the checkbox to make it clear to the
4680
// user that we are not using this any more
4682
checkLimitOutput->SetValue(false);
4519
4685
void MainWindowFrame::OnCacheRamUsageSpin(wxSpinEvent &event)
4521
4687
ASSERT(event.GetPosition() >= 0 &&event.GetPosition()<=100);
4611
4780
// as we can't abort it anyway.
4612
4781
if(event.CanVeto())
4614
if(visControl.numFilters() || visControl.numCams() > 1)
4783
if(visControl.stateModifyLevel() >= STATE_MODIFIED_ANCILLARY)
4616
4785
//Prompt for close
4617
4786
wxMessageDialog *wxD =new wxMessageDialog(this,
4860
5033
panelTop->setMouseZoomFactor((float)zoomRate/100.0f);
4861
5034
panelTop->setMouseMoveFactor((float)moveRate/100.0f);
5037
//If the config file has a max points value stored, use it,
5038
// but don't force a refresh, as we will do that later
5039
if(configFile.getHaveMaxPoints())
5042
stream_cast(s,configFile.getMaxPoints());
5044
textLimitOutput->SetValue(wxStr(s));
5046
visControl.setIonDisplayLimit(configFile.getMaxPoints());
4864
5050
void MainWindowFrame::restoreConfigPanelDefaults()
5228
5416
wxFileName fileNaming(wxStr(removeFiles[ui]));
5229
5417
wxCopyFile(wxStr(removeFiles[ui]),wxtmpDir+fileNaming.GetFullName());
5231
//if the copy works or not, just delete the autosave anyway
5419
//if the copy works or not, just delete the autsave anyway
5232
5420
wxRemoveFile(wxStr(removeFiles[ui]));
5424
void MainWindowFrame::setSaveStatus()
5427
(visControl.stateModifyLevel() >=STATE_MODIFIED_ANCILLARY)
5428
&& visControl.getFilename().size());
5236
5431
wxSize MainWindowFrame::getNiceWindowSize() const
5238
5433
wxDisplay *disp=new wxDisplay;
5284
5479
checkAlphaBlend->SetToolTip(wxTRANS("Enable/Disable \"Alpha blending\" (transparency) in rendering system. Blending is used to smooth objects (avoids artefacts known as \"jaggies\") and to make transparent surfaces. Disabling will provide faster rendering but look more blocky"));
5285
5480
checkLighting->SetToolTip(wxTRANS("Enable/Disable lighting calculations in rendering, for objects that request this. Lighting provides important depth cues for objects comprised of 3D surfaces. Disabling may allow faster rendering in complex scenes"));
5286
5481
checkWeakRandom->SetToolTip(wxTRANS("Enable/Disable weak randomisation (Galois linear feedback shift register). Strong randomisation uses a much slower random selection method, but provides better protection against inadvertent correlations, and is recommended for final analyses"));
5483
checkLimitOutput->SetToolTip(wxTRANS("Limit the number of points that can be displayed in the 3D scene. Does not affect filter tree calculations. Disabling this can severely reduce performance, due to large numbers of points being visible at once."));
5287
5484
checkCaching->SetToolTip(wxTRANS("Enable/Disable caching of intermediate results during filter updates. Disabling caching will use less system RAM, though changes to any filter property will cause the entire filter tree to be recomputed, greatly slowing computations"));
5289
5486
gridFilterPropGroup->CreateGrid(0, 2);
5369
5566
wxBoxSizer* sizerLeft = new wxBoxSizer(wxVERTICAL);
5370
5567
wxBoxSizer* sizerTools = new wxBoxSizer(wxVERTICAL);
5371
5568
wxBoxSizer* sizerToolsRamUsage = new wxBoxSizer(wxHORIZONTAL);
5569
wxBoxSizer* sizer_1 = new wxBoxSizer(wxHORIZONTAL);
5372
5570
wxBoxSizer* postProcessSizer = new wxBoxSizer(wxVERTICAL);
5373
5571
wxBoxSizer* sizerFxStereo = new wxBoxSizer(wxVERTICAL);
5374
5572
wxBoxSizer* sizerSetereoBaseline = new wxBoxSizer(wxHORIZONTAL);
5466
5664
noteEffects->AddPage(noteFxPanelStereo, wxTRANS("Stereo"));
5467
5665
postProcessSizer->Add(noteEffects, 1, wxEXPAND, 0);
5468
5666
notePost->SetSizer(postProcessSizer);
5667
sizerTools->Add(labelAppearance, 0, wxTOP, 3);
5469
5668
sizerTools->Add(checkAlphaBlend, 0, wxLEFT|wxTOP|wxBOTTOM, 5);
5470
5669
sizerTools->Add(checkLighting, 0, wxLEFT|wxTOP|wxBOTTOM, 6);
5670
sizerTools->Add(static_line_1, 0, wxEXPAND, 0);
5671
sizerTools->Add(labelPerformance, 0, wxTOP, 3);
5471
5672
sizerTools->Add(checkWeakRandom, 0, wxLEFT|wxTOP|wxBOTTOM, 5);
5673
sizer_1->Add(checkLimitOutput, 0, wxRIGHT, 3);
5674
sizer_1->Add(textLimitOutput, 0, wxLEFT, 4);
5675
sizerTools->Add(sizer_1, 0, wxLEFT|wxEXPAND, 5);
5472
5676
sizerTools->Add(checkCaching, 0, wxLEFT|wxTOP|wxBOTTOM, 5);
5473
5677
sizerToolsRamUsage->Add(labelMaxRamUsage, 0, wxRIGHT|wxALIGN_RIGHT, 5);
5474
5678
sizerToolsRamUsage->Add(spinCachePercent, 0, 0, 5);