diff --git a/helper_methods/ksptot_ma/launch_vehicle_designer/classes/UndoRedo/@LVD_UndoRedoState/LVD_UndoRedoState.m b/helper_methods/ksptot_ma/launch_vehicle_designer/classes/UndoRedo/@LVD_UndoRedoState/LVD_UndoRedoState.m new file mode 100644 index 000000000..7d7f969a8 --- /dev/null +++ b/helper_methods/ksptot_ma/launch_vehicle_designer/classes/UndoRedo/@LVD_UndoRedoState/LVD_UndoRedoState.m @@ -0,0 +1,21 @@ +classdef LVD_UndoRedoState < matlab.mixin.SetGet + %LVD_UndoRedoState Summary of this class goes here + % Detailed explanation goes here + + properties + serialLvdData uint8 + actionName(1,:) char + end + + methods + function obj = LVD_UndoRedoState(lvdData, actionName) + obj.serialLvdData = getByteStreamFromArray(lvdData); + obj.actionName = actionName; + end + + function [lvdData, actionName] = getUndoData(obj) + lvdData = getArrayFromByteStream(obj.serialLvdData); + actionName = obj.actionName; + end + end +end \ No newline at end of file diff --git a/helper_methods/ksptot_ma/launch_vehicle_designer/classes/UndoRedo/@LVD_UndoRedoStateSet/LVD_UndoRedoStateSet.m b/helper_methods/ksptot_ma/launch_vehicle_designer/classes/UndoRedo/@LVD_UndoRedoStateSet/LVD_UndoRedoStateSet.m new file mode 100644 index 000000000..c8a01b683 --- /dev/null +++ b/helper_methods/ksptot_ma/launch_vehicle_designer/classes/UndoRedo/@LVD_UndoRedoStateSet/LVD_UndoRedoStateSet.m @@ -0,0 +1,87 @@ +classdef LVD_UndoRedoStateSet < matlab.mixin.SetGet + %LVD_UndoRedoStateSet Summary of this class goes here + % Detailed explanation goes here + + properties + undo_states(:,1) LVD_UndoRedoState + undo_pointer (1,1) double = 0 + end + + methods + function obj = LVD_UndoRedoStateSet() + obj.undo_states = LVD_UndoRedoState.empty(1,0); + end + + function addState(obj, hLvdFig, lvdData, actionName) + if(obj.undo_pointer > length(obj.undo_states)) + error('Undo/redo states and the pointer are out of sync.'); + end + + if(obj.undo_pointer == 0) + obj.undo_states = LVD_UndoRedoState.empty(1,0); + obj.undo_states(end+1) = LVD_UndoRedoState(lvdData, actionName); + obj.undo_pointer = 1; + else + t_undo_states = obj.undo_states(1:obj.undo_pointer,:); + t_undo_states(end+1) = LVD_UndoRedoState(lvdData, actionName); + obj.undo_states = t_undo_states; + obj.undo_pointer = obj.undo_pointer + 1; + end + + maxUndos = 25; + if(obj.undo_pointer>maxUndos) + obj.undo_states = obj.undo_states(end-(maxUndos-1):end,:); + obj.undo_pointer = maxUndos; + end + + curName = get(hLvdFig,'Name'); + if(~strcmpi(curName(end),'*')) + set(hLvdFig,'Name',[curName,'*']); + end + end + + function lvdData = undo(obj, curLvdData) + lvdData = LvdData.empty(0,1); + if(obj.undo_pointer < 1 || obj.undo_pointer > length(obj.undo_states)) + return; + end + + if(obj.undo_pointer == length(obj.undo_states)) + obj.undo_states(end+1) = LVD_UndoRedoState(curLvdData, ''); + end + + lvdData = obj.undo_states(obj.undo_pointer).getUndoData(); + obj.undo_pointer = obj.undo_pointer - 1; + end + + function lvdData = redo(obj) + lvdData = LvdData.empty(0,1); + if(obj.undo_pointer + 1 < 1 || obj.undo_pointer + 2 > length(obj.undo_states)) + return; + end + + lvdData = obj.undo_states(obj.undo_pointer+2).getUndoData(); + obj.undo_pointer = obj.undo_pointer + 1; + end + + function [tf, undoActionName] = shouldUndoMenuBeEnabled(obj) + if(obj.undo_pointer > 0) + undoActionName = obj.undo_states(obj.undo_pointer).actionName; + tf = true; + else + undoActionName = ''; + tf = false; + end + end + + function [tf, redoActionName] = shouldRedoMenuBeEnabled(obj) + if(obj.undo_pointer + 1 > 0 && obj.undo_pointer + 1 < length(obj.undo_states)) + redoActionName = obj.undo_states(obj.undo_pointer+1).actionName; + tf = true; + else + redoActionName = ''; + tf = false; + end + end + end +end \ No newline at end of file diff --git a/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.fig b/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.fig index 02c8737c3..7721a5508 100644 Binary files a/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.fig and b/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.fig differ diff --git a/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.m b/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.m index df5f36e9c..a6e683f2f 100644 --- a/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.m +++ b/kspTOT_MissionArchitect/LaunchVehicleDesigner/ma_LvdMainGUI.m @@ -22,7 +22,7 @@ % Edit the above text to modify the response to help ma_LvdMainGUI -% Last Modified by GUIDE v2.5 08-Oct-2018 13:26:49 +% Last Modified by GUIDE v2.5 08-Oct-2018 14:27:31 % Begin initialization code - DO NOT EDIT gui_Singleton = 1; @@ -62,8 +62,7 @@ function ma_LvdMainGUI_OpeningFcn(hObject, eventdata, handles, varargin) setappdata(hObject,'current_save_location',''); setappdata(hObject,'application_title','KSP TOT Launch Vehicle Designer'); -% setappdata(hObject,'undo_states',{}); -% setappdata(hObject,'undo_pointer',0); + setappdata(hObject,'undoRedo',LVD_UndoRedoStateSet()); lvdData = LvdData.getDefaultLvdData(celBodyData); setappdata(handles.ma_LvdMainGUI,'lvdData',lvdData); @@ -133,6 +132,12 @@ function runScript(handles, lvdData) % Get default command line output from handles structure varargout{1} = handles.output; + +function addUndoState(handles,actionName) + lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + undoRedo = getappdata(handles.ma_LvdMainGUI,'undoRedo'); + + undoRedo.addState(handles.ma_LvdMainGUI, lvdData, actionName) % --- Executes on selection change in scriptListbox. function scriptListbox_Callback(hObject, eventdata, handles) @@ -143,6 +148,8 @@ function scriptListbox_Callback(hObject, eventdata, handles) % Hints: contents = cellstr(get(hObject,'String')) returns scriptListbox contents as cell array % contents{get(hObject,'Value')} returns selected item from scriptListbox if(strcmpi(get(handles.ma_LvdMainGUI,'SelectionType'),'open')) + addUndoState(handles,'Edit Event'); + eventNum = get(hObject,'Value'); lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); @@ -174,6 +181,8 @@ function insertEventButton_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + addUndoState(handles,'Insert Event'); + selEvtNum = get(handles.scriptListbox,'Value'); event = LaunchVehicleEvent.getDefaultEvent(lvdData.script); lvdData.script.addEventAtInd(event,selEvtNum); @@ -191,6 +200,8 @@ function moveEventDown_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + addUndoState(handles,'Move Event Down'); + eventNum = get(handles.scriptListbox,'Value'); lvdData.script.moveEvtAtIndexDown(eventNum); @@ -208,6 +219,8 @@ function deleteEvent_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + addUndoState(handles,'Delete Event'); + eventNum = get(handles.scriptListbox,'Value'); lvdData.script.removeEventFromIndex(eventNum); @@ -230,6 +243,8 @@ function moveEventUp_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + addUndoState(handles,'Move Event Up'); + eventNum = get(handles.scriptListbox,'Value'); lvdData.script.moveEvtAtIndexUp(eventNum); @@ -323,6 +338,8 @@ function optimizeMissionMenu_Callback(hObject, eventdata, handles) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); writeOutput = getappdata(handles.ma_LvdMainGUI,'write_to_output_func'); + addUndoState(handles,'Optimize Mission'); + lvdData.optimizer.optimize(writeOutput); runScript(handles, lvdData); @@ -342,6 +359,8 @@ function editLaunchVehicleMenu_Callback(hObject, eventdata, handles) % handles structure with handles and user data (see GUIDATA) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + addUndoState(handles,'Edit Launch Vehicle'); + lvd_editLaunchVehicle(lvdData); runScript(handles, lvdData); @@ -362,6 +381,9 @@ function editConstraintsMenu_Callback(hObject, eventdata, handles) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + + addUndoState(handles,'Edit Constraints'); + lvd_EditConstraintsGUI(lvdData); runScript(handles, lvdData); @@ -375,6 +397,8 @@ function editInitialStateMenu_Callback(hObject, eventdata, handles) lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); hKsptotMainGUI = getappdata(handles.ma_LvdMainGUI,'ksptotMainGUI'); + addUndoState(handles,'Edit Initial State'); + lvd_EditInitialStateGUI(lvdData, hKsptotMainGUI); runScript(handles, lvdData); @@ -522,8 +546,7 @@ function newMissionPlanMenu_Callback(hObject, eventdata, handles, varargin) return; end -% setappdata(handles.ma_MainGUI,'undo_states',{}); -% setappdata(handles.ma_MainGUI,'undo_pointer',0); + setappdata(handles.ma_LvdMainGUI,'undoRedo',LVD_UndoRedoStateSet()); celBodyData = getappdata(handles.ma_LvdMainGUI,'celBodyData'); write_to_output_func = getappdata(handles.ma_LvdMainGUI,'write_to_output_func'); @@ -584,8 +607,7 @@ function openMissionPlanMenu_Callback(hObject, eventdata, handles) load(filePath); if(exist('lvdData','var')) -% setappdata(handles.ma_MainGUI,'undo_states',{}); -% setappdata(handles.ma_MainGUI,'undo_pointer',0); + setappdata(handles.ma_LvdMainGUI,'undoRedo',LVD_UndoRedoStateSet()); if(isfield(lvdData,'celBodyData') && ... length(fields(celBodyData.sun)) == length(fields(lvdData.celBodyData.sun))) %#ok @@ -731,3 +753,114 @@ function saveMissionPlanToolbar_ClickedCallback(hObject, eventdata, handles) set(handles.newMissionPlanToolbar,'Enable','on'); set(handles.openMissionPlanToolbar,'Enable','on'); set(handles.saveMissionPlanToolbar,'Enable','on'); + + +% -------------------------------------------------------------------- +function editMenu_Callback(hObject, eventdata, handles) +% hObject handle to editMenu (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + undoRedo = getappdata(handles.ma_LvdMainGUI,'undoRedo'); + [undoTf, undoActionName] = undoRedo.shouldUndoMenuBeEnabled(); + [redoTf, redoActionName] = undoRedo.shouldRedoMenuBeEnabled(); + + if(undoTf) + set(handles.undoMenu,'Enable','on'); + else + set(handles.undoMenu,'Enable','off'); + end + set(handles.undoMenu,'Label',['Undo ',undoActionName]); + + if(redoTf) + set(handles.redoMenu,'Enable','on'); + else + set(handles.redoMenu,'Enable','off'); + end + set(handles.redoMenu,'Label',['Redo ',redoActionName]); + +% -------------------------------------------------------------------- +function undoMenu_Callback(hObject, eventdata, handles) +% hObject handle to undoMenu (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + lvdData = getappdata(handles.ma_LvdMainGUI,'lvdData'); + undoRedo = getappdata(handles.ma_LvdMainGUI,'undoRedo'); + lvdData = undoRedo.undo(lvdData); + + setappdata(handles.ma_LvdMainGUI,'lvdData',lvdData); + + runScript(handles, lvdData); + lvd_processData(handles); + + curName = get(handles.ma_LvdMainGUI,'Name'); + if(~strcmpi(curName(end),'*')) + set(handles.ma_MainGUI,'Name',[curName,'*']); + end + + editMenu_Callback([], [], handles); + +% -------------------------------------------------------------------- +function redoMenu_Callback(hObject, eventdata, handles) +% hObject handle to redoMenu (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + undoRedo = getappdata(handles.ma_LvdMainGUI,'undoRedo'); + lvdData = undoRedo.redo(); + + if(not(isempty(lvdData))) + setappdata(handles.ma_LvdMainGUI,'lvdData',lvdData); + + runScript(handles, lvdData); + lvd_processData(handles); + end + + curName = get(handles.ma_LvdMainGUI,'Name'); + if(~strcmpi(curName(end),'*')) + set(handles.ma_MainGUI,'Name',[curName,'*']); + end + + editMenu_Callback([], [], handles); + + +% --- Executes when user attempts to close ma_LvdMainGUI. +function ma_LvdMainGUI_CloseRequestFcn(hObject, eventdata, handles) +% hObject handle to ma_LvdMainGUI (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: delete(hObject) closes the figure + if(strcmpi(handles.scriptWorkingLbl.Visible,'on') || ... + strcmpi(handles.plotWorkingLbl.Visible,'on')) + askToQuit = true; + else + askToQuit = false; + end + + yesStr = 'Yes'; + if(askToQuit) + response = questdlg(['KSPTOT is still processing. Any in-work data will be lost upon closing. Continue?'],'Close Mission Architect?',yesStr,'No','No'); + else + response = yesStr; + end + + if(~strcmpi(response,yesStr)) + return; + else + if(isMissionPlanSaved(handles)) + askToClear = false; + else + askToClear = true; + end + + if(askToClear) + response = questdlg(['All unsaved work will be lost. Continue?'],'Close Launch Vehicle Designer?',yesStr,'No','No'); + else + response = yesStr; + end + + if(~strcmpi(response,yesStr)) + return; + end + + delete(hObject); + end diff --git a/kspTOT_MissionArchitect/ma_MainGUI.fig b/kspTOT_MissionArchitect/ma_MainGUI.fig index e908609c5..4efa02365 100644 Binary files a/kspTOT_MissionArchitect/ma_MainGUI.fig and b/kspTOT_MissionArchitect/ma_MainGUI.fig differ