~ubuntu-branches/ubuntu/trusty/3depict/trusty-proposed

« back to all changes in this revision

Viewing changes to src/gui/mainFrame.cpp

  • Committer: Package Import Robot
  • Author(s): D Haley
  • Date: 2013-07-20 18:31:32 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20130720183132-5ak932y2x6pwo4fs
Tags: 0.0.14-1
* Update to upstream, 0.0.14
* Enable mathgl2.x configure option
* Modify build-depends, libmgl-dev >= 2.1.32

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *      3Depict.h - main program header
3
 
 *      Copyright (C) 2013 D Haley
4
 
 *
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.
9
 
 
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.
14
 
 
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/>.
17
 
*/
18
 
 
19
1
#include "mainFrame.h"
20
2
 
21
3
#ifdef __APPLE__
96
78
const unsigned int MIN_WIN_HEIGHT=100;
97
79
 
98
80
 
 
81
 
99
82
//!Number of pages in the panel at the bottom
100
83
const unsigned int NOTE_CONSOLE_PAGE_OFFSET= 2;
101
84
 
253
236
    //Options panel
254
237
    ID_CHECK_ALPHA,
255
238
    ID_CHECK_LIGHTING,
 
239
    ID_CHECK_LIMIT_POINT_OUT,
 
240
    ID_TEXT_LIMIT_POINT_OUT,
256
241
    ID_CHECK_CACHING,
257
242
    ID_CHECK_WEAKRANDOM,
258
243
    ID_SPIN_CACHEPERCENT,
267
252
 
268
253
};
269
254
 
 
255
enum
 
256
{
 
257
        FILE_OPEN_TYPE_UNKNOWN=1,
 
258
        FILE_OPEN_TYPE_XML=2,
 
259
        FILE_OPEN_TYPE_POS=4,
 
260
        FILE_OPEN_TYPE_TEXT=8
 
261
};
 
262
 
270
263
 
271
264
void setWxTreeImages(wxTreeCtrl *t, const map<size_t, wxArtID> &artFilters)
272
265
{
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);
276
269
#else
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)
285
278
        {
286
 
                #if defined(__WIN32) || defined(__WIN64)
 
279
                #if defined(__WIN32) || defined(__WIN64) || defined(__APPLE__)
287
280
 
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();
 
351
 
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);
400
395
 
401
396
 
402
 
        bool glPanelOK;
403
397
#if wxCHECK_VERSION(2,9,0)
404
398
        glPanelOK = panelTop->displaySupported();
405
399
#else
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));
 
629
    std::string tmpStr;
 
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);
764
767
 
765
768
        //delete the file history  pointer
766
769
        delete recentHistory;
767
 
    
 
770
   
 
771
        //Bindings did not get initialised, if glpane is not OK,
 
772
        // so abort, rather than disconnecting
 
773
        if(!glPanelOK)
 
774
                return; 
768
775
 
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)
873
883
  
874
884
 
875
885
    EVT_COMMAND(wxID_ANY, RemoteUpdateAvailEvent, MainWindowFrame::OnCheckUpdatesThread)
877
887
END_EVENT_TABLE();
878
888
 
879
889
 
 
890
unsigned int MainWindowFrame::guessFileType(const std::string &dataFile)
 
891
{
 
892
        
 
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.
 
895
        wxFileName fname;
 
896
        wxString volume,path,name,ext;
 
897
        bool hasExt;
 
898
        fname.SplitPath(wxStr(dataFile),&volume,
 
899
                        &path,&name,&ext, &hasExt);
 
900
 
 
901
        //Test the extension to determine what we will do
 
902
        //TODO: This is really lazy, and I should use something like libmagic.
 
903
        std::string extStr;
 
904
        extStr=stlStr(ext);
 
905
 
 
906
        if( extStr == std::string("xml"))
 
907
                return FILE_OPEN_TYPE_XML;
 
908
        
 
909
        if( extStr == std::string("txt"))
 
910
                return FILE_OPEN_TYPE_TEXT;
 
911
 
 
912
        if( extStr == std::string("pos"))
 
913
                return FILE_OPEN_TYPE_POS;
 
914
 
 
915
        return FILE_OPEN_TYPE_UNKNOWN;
 
916
}
 
917
 
 
918
 
880
919
bool MainWindowFrame::getTreeFilterId(const wxTreeItemId &tId, size_t &filterId) const
881
920
{
882
921
        if(!tId.IsOk())
892
931
        return true;
893
932
}
894
933
 
 
934
void MainWindowFrame::checkAskSaveState()
 
935
{
 
936
 
 
937
        if(visControl.hasStateData() && visControl.stateModifyLevel() >=STATE_MODIFIED_ANCILLARY)
 
938
        {
 
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);
 
944
 
 
945
                if ( wxD->ShowModal()== wxID_YES) 
 
946
                {
 
947
                        wxCommandEvent event;
 
948
                        OnFileSave(event);
 
949
                }
 
950
        }
 
951
}
895
952
 
896
953
void MainWindowFrame::OnFileOpen(wxCommandEvent &event)
897
954
{
899
956
        if(currentlyUpdatingScene || visControl.isRefreshing())
900
957
                return;
901
958
 
 
959
 
 
960
 
 
961
 
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))
908
968
                return;
909
969
 
 
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)
 
974
                checkAskSaveState();
 
975
                
 
976
        
 
977
        
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
963
1031
        statusMessage(TRANS("Merged file."),MESSAGE_INFO);
964
1032
 
965
1033
        panelTop->Refresh();
 
1034
 
 
1035
        setSaveStatus();
966
1036
        
967
1037
        wxF->Destroy();
968
1038
}
1079
1149
 
1080
1150
bool MainWindowFrame::loadFile(const wxString &fileStr, bool merge)
1081
1151
{
1082
 
 
1083
1152
        //Don't try to alter viscontrol if we are refreshing. That would be bad.
1084
1153
        ASSERT(!visControl.isRefreshing());
 
1154
        
1085
1155
        std::string dataFile = stlStr(fileStr);
 
1156
        unsigned int fileType=guessFileType(dataFile);
1086
1157
        
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.
1089
 
        wxFileName fname;
1090
 
        wxString volume,path,name,ext;
1091
 
        bool hasExt;
1092
 
        fname.SplitPath(fileStr,&volume,
1093
 
                        &path,&name,&ext, &hasExt);
1094
 
 
1095
 
        //Test the extension to determine what we will do
1096
 
        //TODO: This is really lazy, and I should use something like libmagic.
1097
 
        std::string extStr;
1098
 
        extStr=stlStr(ext);
1099
 
        if( extStr == std::string("xml"))
 
1158
        if(fileType == FILE_OPEN_TYPE_XML)
1100
1159
        {
1101
1160
                std::stringstream ss;
1102
1161
                
1117
1176
                        return false;
1118
1177
                }
1119
1178
 
1120
 
                //Try to restore the working directory as needed
1121
 
                if(!(visControl.getWorkDir().size()))
1122
 
                {
1123
 
                        wxString wd;
1124
 
                        wd = wxGetCwd();
1125
 
                        visControl.setWorkDir(stlStr(wd));
1126
 
                }
1127
 
                else
1128
 
                {
1129
 
                        if(wxDirExists(wxStr(visControl.getWorkDir())))
1130
 
                                wxSetWorkingDirectory(wxStr(visControl.getWorkDir()));
1131
 
                }
1132
 
 
1133
 
 
1134
1179
 
1135
1180
                if(visControl.hasHazardousContents())
1136
1181
                {
1152
1197
 
1153
1198
                checkViewWorldAxis->Check(visControl.getAxisVisible());
1154
1199
 
 
1200
                {
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);
1158
1204
 
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++)
1163
1207
                {
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
1168
1212
                        //the ID
1169
 
                        if(camData[ui].first == visControl.getActiveCamId())
1170
 
                        {
 
1213
                        if(ui == visControl.getActiveCamId())
1171
1214
                                comboCamera->SetSelection(ui-1);
1172
 
                                uniqueID=camData[ui].first;
1173
 
                        }
1174
1215
                }
1175
1216
 
1176
1217
                //Only update the camera grid if we have a valid uniqueID
1177
 
                if(camData.size() > 1)
 
1218
                if(camNames.size() > 1)
1178
1219
                {
1179
1220
                        //Use the remembered ID to update the grid.
1180
 
                        visControl.updateCamPropertyGrid(gridCameraProperties,uniqueID);
 
1221
                        visControl.updateCamPropertyGrid(gridCameraProperties,
 
1222
                                                visControl.getActiveCamId());
1181
1223
                }
1182
1224
                else
1183
1225
                {
1185
1227
                        gridCameraProperties->clear();
1186
1228
                        comboCamera->SetValue(wxCStr(TRANS(cameraIntroString)));
1187
1229
                }
 
1230
                }
1188
1231
 
1189
1232
                //reset the stash combo box
1190
1233
                comboStash->SetValue(wxCStr(TRANS(stashIntroString)));
1201
1244
 
1202
1245
 
1203
1246
 
1204
 
                currentFile =fileStr;
1205
1247
                fileSave->Enable(true);
1206
1248
 
1207
1249
                
1227
1269
 
1228
1270
                FilterTree fTree;
1229
1271
 
1230
 
                Filter *posFilter,*downSampleFilter;
 
1272
                Filter *posFilter;
1231
1273
                posFilter= configFile.getDefaultFilter(FILTER_TYPE_DATALOAD);
1232
 
                downSampleFilter= configFile.getDefaultFilter(FILTER_TYPE_IONDOWNSAMPLE);
1233
1274
 
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;
1239
1280
                else
1240
1281
                        fileMode=DATALOAD_FLOAT_FILE;
1251
1292
 
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);
1256
1296
 
1257
 
                currentFile.clear();
1258
1297
        }       
1259
1298
 
1260
1299
        visControl.updateWxTreeCtrl(treeFilters);
1282
1321
                if(getTreeFilterId(treeFilters->GetSelection(),filterId))
1283
1322
                        visControl.setWxTreeFilterViewPersistence(filterId);
1284
1323
 
1285
 
 
1286
1324
                bool loadOK=false;
1287
1325
                if(!wxFileExists(f))
1288
1326
                        statusMessage("File does not exist",MESSAGE_ERROR);
1289
 
                else if(loadFile(f))
 
1327
                else 
1290
1328
                {
1291
 
                        if(loadOK)
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();
 
1332
                
 
1333
                        if(loadFile(f))
 
1334
                        {
 
1335
                                if(loadOK)
 
1336
                                        statusMessage(TRANS("Loaded file."),MESSAGE_INFO);
 
1337
                                panelTop->Refresh();
 
1338
                        }
1294
1339
                }
1295
1340
                
1296
1341
                if(!loadOK)
1300
1345
                        recentHistory->RemoveFileFromHistory(event.GetId()-wxID_FILE1);
1301
1346
                        configFile.removeRecentFile(stlStr(f));
1302
1347
                }
 
1348
                
 
1349
                setSaveStatus();
1303
1350
        }
 
1351
 
1304
1352
}
1305
1353
 
1306
1354
void MainWindowFrame::OnFileSave(wxCommandEvent &event)
1307
1355
{
1308
 
        if(!currentFile.length())
1309
 
                return;
 
1356
        std::string saveFilename=visControl.getFilename();
1310
1357
 
 
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)))
1313
1362
        {
1314
1363
                OnFileSaveAs(event);
1315
 
 
1316
1364
                return;
1317
1365
        }
1318
 
 
1319
1366
        
1320
1367
        std::map<string,string> dummyMap;
1321
 
        std::string dataFile = stlStr(currentFile);
1322
 
 
1323
1368
        //Try to save the viscontrol state
1324
 
        if(!visControl.saveState(dataFile.c_str(),dummyMap))
 
1369
        if(!visControl.saveState(saveFilename.c_str(),dummyMap))
1325
1370
        {
1326
1371
                wxErrMsg(this,TRANS("Save error"),TRANS("Unable to save. Check output destination can be written to."));
1327
1372
        }
1328
1373
        else
1329
1374
        {
1330
 
                fileSave->Enable(true);
1331
 
 
1332
1375
                //Update the recent files, and the menu.
1333
 
                configFile.addRecentFile(dataFile);
1334
 
                recentHistory->AddFileToHistory(wxStr(dataFile));
1335
 
                
1336
 
                dataFile=std::string("Saved state: ") + dataFile;
1337
 
                statusMessage(dataFile.c_str(),MESSAGE_INFO);
 
1376
                configFile.addRecentFile(saveFilename);
 
1377
                recentHistory->AddFileToHistory(wxStr(saveFilename));
 
1378
        
 
1379
                std::string tmpStr;
 
1380
                tmpStr= std::string("Saved state: ") + saveFilename;
 
1381
                statusMessage(tmpStr.c_str(),MESSAGE_INFO);
1338
1382
 
1339
1383
        }
1340
1384
 
 
1385
        setSaveStatus();
1341
1386
}
1342
1387
 
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);
1624
1671
 
1625
1672
                        fileMenu->Enable(ID_FILE_OPEN,!locking);
1626
1673
                        fileMenu->Enable(ID_FILE_MERGE,!locking);
1627
 
                        fileMenu->Enable(ID_FILE_SAVE,!locking);
 
1674
 
 
1675
                        //Save menu needs to be handled specially in the case of an unlock
 
1676
                        // as determining if it can be enabled needs work
 
1677
                        if(!locking)
 
1678
                                fileMenu->Enable(ID_FILE_SAVE,false);
 
1679
                        else
 
1680
                                setSaveStatus();
 
1681
 
1628
1682
                        fileMenu->Enable(ID_FILE_SAVEAS,!locking);
1629
1683
 
1630
1684
                        for(size_t ui=0;ui<recentFilesMenu->GetMenuItemCount();ui++)
1657
1711
 
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);
 
1715
                        
 
1716
                        //Save menu needs to be handled specially in the case of an unlock
 
1717
                        // as determining if it can be enabled needs work
 
1718
                        if(!locking)
 
1719
                                fileMenu->Enable(ID_FILE_SAVE,false);
 
1720
                        else
 
1721
                                setSaveStatus();
1662
1722
 
 
1723
                        //Lock/unlock all the recent files entries
1663
1724
                        for(size_t ui=0;ui<recentFilesMenu->GetMenuItemCount();ui++)
1664
1725
                        {
1665
1726
                                wxMenuItem *m;
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);
1679
1742
 
 
1743
 
1680
1744
                        //Lock panel spectra, so we cannot alter things like ranges
1681
1745
                        panelSpectra->limitInteraction(locking);
1682
1746
                        break;
1786
1850
                        {
1787
1851
                                if(exportDialog->wantsImages())
1788
1852
                                {
 
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))
1792
1857
                                        {
1793
1858
                                                pair<string,string> errMsg;
1794
1859
                                                string tmpStr;
2284
2349
        }
2285
2350
        else
2286
2351
        {
2287
 
                currentFile = wxF->GetPath();
2288
 
                fileSave->Enable(true);
 
2352
                std::string tmpStr;
 
2353
                tmpStr=stlStr(wxF->GetPath());
 
2354
                visControl.setFilename(tmpStr);
2289
2355
 
2290
2356
                //Update the recent files, and the menu.
2291
2357
                configFile.addRecentFile(dataFile);
2297
2363
 
2298
2364
        //Restore the relative path behaviour
2299
2365
        visControl.setUseRelPaths(oldRelPath);
 
2366
        
 
2367
        setSaveStatus();
2300
2368
}
2301
2369
 
2302
2370
 
3184
3252
        
3185
3253
                        //Force a scene update, independent of if autoUpdate is enabled. 
3186
3254
                        doSceneUpdate();        
3187
 
 
 
3255
                
3188
3256
                        break;
3189
3257
                }
3190
3258
                default:
3234
3302
                clearWxTreeImages(treeFilters);
3235
3303
 
3236
3304
        visControl.updateFilterPropGrid(gridFilterPropGroup,filterId);
3237
 
        
 
3305
 
3238
3306
        Layout();
3239
3307
        programmaticEvent=false;
3240
3308
}
3333
3401
                //refresh the camera property grid
3334
3402
                visControl.updateCamPropertyGrid(gridCameraProperties ,l->value);
3335
3403
 
 
3404
                setSaveStatus();
 
3405
 
3336
3406
                //force redraw in 3D pane
3337
3407
                panelTop->Refresh(false);
3338
3408
                return ;
3350
3420
        visControl.setCam(u);
3351
3421
        visControl.updateCamPropertyGrid(gridCameraProperties,u);
3352
3422
        panelTop->Refresh(false);
 
3423
 
 
3424
        setSaveStatus();
3353
3425
}
3354
3426
 
3355
3427
void MainWindowFrame::OnComboCamera(wxCommandEvent &event)
3367
3439
        statusMessage(s.c_str(),MESSAGE_INFO);
3368
3440
        
3369
3441
        panelTop->Refresh(false);
 
3442
        
 
3443
        setSaveStatus();
3370
3444
        return ;
3371
3445
}
3372
3446
 
3510
3584
                doSceneUpdate();
3511
3585
 
3512
3586
        comboFilters->SetValue(wxT(""));
 
3587
        
3513
3588
}
3514
3589
 
3515
3590
bool MainWindowFrame::doSceneUpdate()
3522
3597
        progressTimer->Start(PROGRESS_TIMER_DELAY);             
3523
3598
        currentlyUpdatingScene=true;
3524
3599
        haveAborted=false;
 
3600
        panelTop->currentScene.setShowProgress(true);
3525
3601
 
3526
3602
                
3527
3603
        statusMessage("",MESSAGE_NONE);
3575
3651
 
3576
3652
        updateLastRefreshBox();
3577
3653
 
 
3654
        panelTop->currentScene.setShowProgress(false);
3578
3655
 
3579
3656
        //Add (or hide) a little "Star" to inform the user there is some info available
3580
3657
        if(textConsoleOut->IsEmpty() || noteDataView->GetSelection()==NOTE_CONSOLE_PAGE_OFFSET)
3593
3670
 
3594
3671
        visControl.updateRawGrid();
3595
3672
 
 
3673
        setSaveStatus();
 
3674
 
3596
3675
        //Return a value dependant upon whether we successfully loaded 
3597
3676
        //the data or not
3598
3677
        return errCode == 0;
3693
3772
        //Save to the autosave file
3694
3773
        std::string s;
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);
3699
 
        else
 
3775
 
 
3776
        //Only save if we have autosave data
 
3777
        if(visControl.hasStateData())
3700
3778
        {
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);
 
3782
                else
 
3783
                {
 
3784
                        //The save failed, but may have left an incomplete file lying around
 
3785
                        if(wxFileExists(filePath))
 
3786
                                wxRemoveFile(filePath);
 
3787
                }
3704
3788
        }
3705
3789
 
3706
3790
 
3763
3847
        {
3764
3848
                //Use the current combobox value to determine which camera is the 
3765
3849
                //current camera in the property grid
3766
 
                
3767
 
 
 
3850
                visControl.getCameraUpdates();
 
3851
                        
3768
3852
                int n = comboCamera->FindString(comboCamera->GetValue());
3769
3853
 
3770
3854
                if(n != wxNOT_FOUND)
3776
3860
                }
3777
3861
 
3778
3862
                panelTop->clearCameraUpdates();
 
3863
 
 
3864
                setSaveStatus();
3779
3865
        }
3780
3866
 
3781
3867
        if(plotUpdates)
3795
3881
 
3796
3882
        }
3797
3883
 
 
3884
 
3798
3885
        programmaticEvent=false;        
3799
3886
}
3800
3887
 
3854
3941
        }
3855
3942
        else
3856
3943
        {
 
3944
                //Check for new progress data
3857
3945
                ProgressData p;
3858
3946
                p=visControl.getProgress();
 
3947
 
 
3948
                if(p == lastProgressData)
 
3949
                        return;
 
3950
                lastProgressData=p;
 
3951
 
 
3952
 
 
3953
                //Update the text progress
 
3954
                {
3859
3955
                ASSERT(p.totalProgress <= visControl.numFilters());
3860
3956
                
3861
3957
                if(p.filterProgress > 100)
3896
3992
                                progressString = totalProg + TRANS(" of ") + totalCount;
3897
3993
                }
3898
3994
 
 
3995
 
3899
3996
                if( p.filterProgress != 100)
3900
3997
                        filterProg+=TRANS("\% Done (Esc aborts)");
3901
3998
                else
3902
3999
                        filterProg+=TRANS("\% Done");
 
4000
                }
 
4001
 
 
4002
                //Update the scene progress icon
 
4003
                if(panelTop->currentScene.getShowProgress())
 
4004
                {
 
4005
                        wxPaintEvent wxP;
 
4006
                        wxPostEvent(panelTop,wxP);
 
4007
                }
 
4008
 
3903
4009
 
3904
4010
        }
3905
4011
 
3907
4013
        MainFrame_statusbar->SetStatusText(wxT(""),0);
3908
4014
        MainFrame_statusbar->SetStatusText(wxStr(progressString),1);
3909
4015
        MainFrame_statusbar->SetStatusText(wxStr(filterProg),2);
 
4016
 
3910
4017
}
3911
4018
 
3912
4019
void MainWindowFrame::updatePostEffects()
4227
4334
                        statusMessage(TRANS("Tip: You can shift-click to force full refresh, if required"),MESSAGE_HINT);
4228
4335
        }
4229
4336
        doSceneUpdate();        
 
4337
        
4230
4338
}
4231
4339
 
4232
4340
void MainWindowFrame::OnRawDataUnsplit(wxSplitterEvent &event)
4370
4478
                else
4371
4479
                        clearWxTreeImages(treeFilters);
4372
4480
        }
 
4481
 
 
4482
        setSaveStatus();
4373
4483
}
4374
4484
 
4375
4485
void MainWindowFrame::OnFilterGridCellEditorHide(wxGridEvent &event)
4464
4574
        }
4465
4575
 
4466
4576
        panelTop->Refresh(false);
4467
 
        
 
4577
 
 
4578
        setSaveStatus();
4468
4579
}
4469
4580
 
4470
4581
void MainWindowFrame::OnButtonGridCopy(wxCommandEvent &event)
4516
4627
        doSceneUpdate();
4517
4628
}
4518
4629
 
 
4630
void MainWindowFrame::OnCheckLimitOutput(wxCommandEvent &event)
 
4631
{
 
4632
        size_t limitVal;
 
4633
        if(event.IsChecked())
 
4634
        {
 
4635
                bool isOK=validateTextAsStream(textLimitOutput,limitVal);
 
4636
 
 
4637
                if(!isOK)
 
4638
                        return;
 
4639
        }
 
4640
        else
 
4641
                limitVal=0;
 
4642
 
 
4643
        visControl.setIonDisplayLimit(limitVal);
 
4644
        doSceneUpdate();
 
4645
        
 
4646
        configFile.setMaxPoints(limitVal);
 
4647
}
 
4648
 
 
4649
void MainWindowFrame::OnTextLimitOutput(wxCommandEvent &event)
 
4650
{
 
4651
        size_t limitVal;
 
4652
        bool isOK=validateTextAsStream(textLimitOutput,limitVal);
 
4653
 
 
4654
        if(!isOK)
 
4655
                return;
 
4656
 
 
4657
        if(checkLimitOutput->IsChecked())
 
4658
        {
 
4659
                visControl.setIonDisplayLimit(limitVal);
 
4660
                configFile.setMaxPoints(limitVal);
 
4661
        }
 
4662
}
 
4663
 
 
4664
void MainWindowFrame::OnTextLimitOutputEnter(wxCommandEvent &event)
 
4665
{
 
4666
        size_t limitVal;
 
4667
        bool isOK=validateTextAsStream(textLimitOutput,limitVal);
 
4668
 
 
4669
        if(!isOK)
 
4670
                return;
 
4671
 
 
4672
        if(checkLimitOutput->IsChecked())
 
4673
        {
 
4674
                visControl.setIonDisplayLimit(limitVal);
 
4675
                doSceneUpdate();
 
4676
        }
 
4677
 
 
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
 
4681
        if(limitVal == 0)
 
4682
                checkLimitOutput->SetValue(false);
 
4683
}
 
4684
 
4519
4685
void MainWindowFrame::OnCacheRamUsageSpin(wxSpinEvent &event)
4520
4686
{
4521
4687
        ASSERT(event.GetPosition() >= 0 &&event.GetPosition()<=100);
4547
4713
                comboCamera->SetValue(wxT(""));
4548
4714
                gridCameraProperties->clear();
4549
4715
                programmaticEvent=false;
 
4716
 
 
4717
                setSaveStatus();
4550
4718
        }
 
4719
        
4551
4720
}
4552
4721
 
4553
4722
void MainWindowFrame::OnSpectraListbox(wxCommandEvent &event)
4611
4780
                // as we can't abort it anyway.
4612
4781
                if(event.CanVeto())
4613
4782
                {
4614
 
                        if(visControl.numFilters() || visControl.numCams() > 1)
 
4783
                        if(visControl.stateModifyLevel() >= STATE_MODIFIED_ANCILLARY)
4615
4784
                        {
4616
4785
                                //Prompt for close
4617
4786
                                wxMessageDialog *wxD  =new wxMessageDialog(this,
4708
4877
        noteFxPanelStereo->Enable(event.IsChecked());
4709
4878
        visControl.setEffects(event.IsChecked());
4710
4879
        updatePostEffects();
 
4880
                
 
4881
        setSaveStatus();
4711
4882
        
4712
4883
        panelTop->Refresh();
4713
4884
}
4729
4900
        labelFxCropDy->Enable(event.IsChecked());
4730
4901
        labelFxCropDz->Enable(event.IsChecked());
4731
4902
 
 
4903
        setSaveStatus();
 
4904
 
4732
4905
        updatePostEffects();
4733
4906
}
4734
4907
 
4859
5032
 
4860
5033
        panelTop->setMouseZoomFactor((float)zoomRate/100.0f);
4861
5034
        panelTop->setMouseMoveFactor((float)moveRate/100.0f);
 
5035
 
 
5036
 
 
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())
 
5040
        {
 
5041
                std::string s;
 
5042
                stream_cast(s,configFile.getMaxPoints());
 
5043
 
 
5044
                textLimitOutput->SetValue(wxStr(s));
 
5045
 
 
5046
                visControl.setIonDisplayLimit(configFile.getMaxPoints());
 
5047
        }
4862
5048
}
4863
5049
 
4864
5050
void MainWindowFrame::restoreConfigPanelDefaults()
5099
5285
                                requireFirstUpdate=true;
5100
5286
                                //Prevent the program from allowing save menu usage
5101
5287
                                //into autosave file
5102
 
                                currentFile.clear();
5103
 
                                fileSave->Enable(false);                
 
5288
                                std::string tmpStr;
 
5289
                                visControl.setFilename(tmpStr);
 
5290
 
 
5291
                                setSaveStatus();
5104
5292
                        }
5105
5293
 
5106
5294
                
5163
5351
                                {
5164
5352
                                        //Prevent the program from allowing save menu usage
5165
5353
                                        //into autosave file
5166
 
                                        currentFile.clear();
5167
 
                                        fileSave->Enable(false);
 
5354
                                        
 
5355
                                        
5168
5356
                                        doErase=true;
5169
5357
                                }
5170
5358
                                else 
5228
5416
                        wxFileName fileNaming(wxStr(removeFiles[ui]));
5229
5417
                        wxCopyFile(wxStr(removeFiles[ui]),wxtmpDir+fileNaming.GetFullName()); 
5230
5418
                }
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]));   
5233
5421
        }
5234
5422
}
5235
5423
 
 
5424
void MainWindowFrame::setSaveStatus()
 
5425
{
 
5426
        fileSave->Enable(
 
5427
                (visControl.stateModifyLevel() >=STATE_MODIFIED_ANCILLARY)
 
5428
                        && visControl.getFilename().size());
 
5429
}
 
5430
 
5236
5431
wxSize MainWindowFrame::getNiceWindowSize() const
5237
5432
{
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"));
 
5482
 
 
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"));
5288
5485
 
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);
5503
5707
    splitLeftRight->SplitVertically(panelLeft, panelRight);
5504
5708
    topSizer->Add(splitLeftRight, 1, wxEXPAND, 0);
5505
5709
    SetSizer(topSizer);
 
5710
    topSizer->Fit(this);
5506
5711
    Layout();
5507
5712
    // end wxGlade
5508
5713
    //