/// <summary> /// Try to fix all broken nodes. Even if a node cannot be fixed, do try to fix the others. /// </summary> /// <returns>Whether all nodes were fixed and hence the path is now fine</returns> public bool AutoFixAllBrokenNodes() { bool fixSucceeded = true; int nodeToTry = 0; Collection <TrainpathNode> brokenNodes = CurrentTrainPath.GetBrokenNodes(); EditorActionAutoFixBrokenNodes actionFixBroken = new EditorActionAutoFixBrokenNodes(); EditorActionFixInvalidNode actionFixInvalid = new EditorActionFixInvalidNode(); while (CurrentTrainPath.IsBroken && (nodeToTry < brokenNodes.Count)) { brokenNodes = CurrentTrainPath.GetBrokenNodes(); TrainpathNode nodeToFix = brokenNodes[nodeToTry]; bool canExecuteBroken = actionFixBroken.MenuState(CurrentTrainPath, nodeToFix, null, UpdateAfterEdits, 0, 0); bool canExecuteInvalid = actionFixInvalid.MenuState(CurrentTrainPath, nodeToFix, null, UpdateAfterEdits, 0, 0); if (canExecuteBroken) { actionFixBroken.DoAction(); brokenNodes = CurrentTrainPath.GetBrokenNodes(); } else if (canExecuteInvalid) { actionFixInvalid.DoAction(); brokenNodes = CurrentTrainPath.GetBrokenNodes(); } else { fixSucceeded = false; nodeToTry++; } } return(fixSucceeded); }
/// <summary> /// Save the names of the stations along the path to a file. /// </summary> public void SaveStationNames() { string[] stationNames = CurrentTrainPath.StationNames(); SaveStationNames saveStationNames = new Editing.SaveStationNames(); saveStationNames.SaveToFile(stationNames); }
/// <summary> /// Undo the last editor action /// </summary> public void Undo() { if (_draggingIsActive) { return; // do not support Undo while dragging } CurrentTrainPath.Undo(); CloseContextMenu(); }
/// <summary> /// Reverse the path including metadata, but first check if the path is clean enough. /// Note that reversing is like any other action, in the sense that it allows an undo. /// </summary> /// <param name="popupX">The screen x-location of where the edit metadata popup needs to be placed</param> /// <param name="popupY">The screen y-location of where the edit metadata popup needs to be placed</param> public void ReversePath(int popupX, int popupY) { if (!CanReverse()) { return; } CurrentTrainPath.StoreCurrentPath(); CurrentTrainPath.ReversePath(); EditMetaData(popupX, popupY); }
/// <summary> /// Redo the last Undo (if available) /// </summary> public void Redo() { if (_draggingIsActive) { return; // do not support Redo while dragging } CurrentTrainPath.Redo(); CloseContextMenu(); OnPathChanged(); }
/// <summary> /// Take a new path indicating a .pat file, load that path and make it into a tail. /// Then try to reconnect the tail. This will then extend the current path with the loaded path /// </summary> /// <param name="path">The path that needs to be loaded to act as an extension</param> public void ExtendWithPath(ORTS.Menu.Path path) { //If everything works as expected, up to three steps are taken that can all be 'Undo'ne: // * Remove End // * Add tail // * Reconnect tail FileName = path.FilePath.Split('\\').Last(); Trainpath newPath = new Trainpath(trackDB, tsectionDat, path.FilePath); // We have a current path and a new path. // First check if the new path is usable TrainpathNode newStart = newPath.FirstNode; if (newPath.FirstNode == null || newPath.FirstNode.NextMainNode == null) { MessageBox.Show(TrackViewer.catalog.GetString("The selected path contains no or only 1 node. The current path was not extended.")); return; } TrainpathNode lastNode = CurrentTrainPath.FirstNode; while (lastNode.NextMainNode != null) { lastNode = lastNode.NextMainNode; } if (CurrentTrainPath.HasEnd) { //We need to remove the end and remember the node for reconnection. //If the end node and the firstnode of the new path are very close together we must make //sure that the junctionnode that will added to replace the end node is not past the firstnode. TrainpathNode endNode = lastNode; lastNode = endNode.PrevNode; EditorActionRemoveEnd actionRemove = new EditorActionRemoveEnd(); bool endCanBeRemoved = actionRemove.MenuState(CurrentTrainPath, endNode, null, UpdateAfterEdits, 0, 0); if (endCanBeRemoved) { //This should always be possible, but we should call MenuState anyway because of some initialization it might be doing actionRemove.DoAction(); CurrentTrainPath.HasEnd = false; } } //Add the tail // The new path contains a startNode that we no longer need, so the tail connects to the next node CurrentTrainPath.StoreCurrentPath(); CurrentTrainPath.FirstNodeOfTail = newPath.FirstNode.NextMainNode; CurrentTrainPath.TailHasEnd = newPath.HasEnd; //Now we try to reconnect the tail automatically EditorActionAutoConnectTail action = new EditorActionAutoConnectTail(); bool actionCanBeExecuted = action.MenuState(CurrentTrainPath, lastNode, null, UpdateAfterEdits, 0, 0); if (actionCanBeExecuted) { action.DoAction(); MessageBox.Show(TrackViewer.catalog.GetString("The selected path has been added as tail and then reconnected.")); } else { MessageBox.Show(TrackViewer.catalog.GetString("The selected path has been added as tail. It was not possible to reconnect automatically.")); } //Make sure all of the path is drawn, so that also the tail is visible ExtendPathFull(); }