/// <summary> /// The constructors for modules need to be emitted in a "from the mainboard out" order. For instance, modules /// connected directly to the mainboard should have their constructor called before modules connected via extenders /// </summary> public IEnumerable <Module> SortModulesInCodeGenerationOrder(out IEnumerable <Issue> issues) { Mainboard mb = this.Mainboard; if (mb == null) { issues = new Issue[0]; return(new Module[0]); } List <Issue> issueBag = new List <Issue>(); var modules = new List <Module>(); while (true) { Module module = this.Modules.FirstOrDefault(m => !modules.Contains(m)); if (module == null) { break; } GetConnectedModules(module, modules, issueBag); } issues = issueBag.Distinct(); return(modules); }
private void GenerateCodeIfNeeded() { if (ModelingDocStore == null) { return; } bool genCode = false; Store store = ModelingDocStore.Store; Mainboard board = store.ElementDirectory.FindElements <Mainboard>().FirstOrDefault(); if (board != null && board.CreatedByNewModel) { //This means we just added a board when the diagram got created (see DSL\Rules\MainboardRules). Let VS know the doc data //is dirty so that the file contents are written out to disk. Without this, the code generation will be based on an empty //diagram. this.SetDocDataDirty(1); genCode = true; } //When a Gadgeteer diagram first gets instantiated we want to trigger the generation of the //Program.generated.cs file right away genCode |= !File.Exists(GetGeneratedCodeFileName()); if (genCode) { RunCodeGeneration(); } }
/// <summary> /// Finds unexplored states and push them into the stack /// </summary> /// <returns>true if any potential connections were found</returns> private static bool FindAndPush(Mainboard mainboard, IEnumerable <SocketUse> mSockets, Stack <PossibleConnection> stack) { SocketUse m = FindUnconnectedSocketUse(mSockets); if (m != null) { PushPosibleConnections(mainboard.Sockets, m, stack); } return(m != null); }
/// <summary> /// The constructors for modules need to be emitted in a "from the mainboard out" order. For instance, modules /// connected directly to the mainboard should have their constructor called before modules connected via extenders /// </summary> public IEnumerable <Module> SortModulesInCodeGenerationOrder() { var modules = new List <Module>(); Mainboard mb = this.Mainboard; if (mb == null) { return(new Module[0]); } GetConnectedModules(mb, modules); //Now fetch unconnected modules. Modules with no sockets (or all-optional sockets) should still generate an instantiation var additionalModules = this.Modules.Where(m => !modules.Contains(m)).ToList(); modules.AddRange(additionalModules); return(modules.Distinct()); //Do distinct because GetModules can return duplicates }
/// <summary> /// Performs a depth-first search to find a suitable configuration where all given modules are connected to the mainboard. /// If this method fails it'll leave the model in the last partially connected state explored. /// </summary> /// <returns>True if a valid configuration was found</returns> public static bool Solve(Mainboard mainboard, IEnumerable <SocketUse> mSockets) { // commented out because of the possiblility of optional sockets //if (mainboard.Sockets.Count < mSockets.Count()) //return false; //Use a stack to store the unexplored states var stack = new Stack <PossibleConnection>(); if (!FindAndPush(mainboard, mSockets, stack)) { return(true); } while (true) { if (stack.Count == 0) { return(false); } var p = stack.Peek(); if (p.Tried) { stack.Pop(); p.Socket.SocketUse = null; } else { p.Tried = true; //Do the connection p.Socket.SocketUse = p.SocketUse; if (!FindAndPush(mainboard, mSockets, stack)) { return(true); } } } }
internal void OnMenuConnectAll(object sender, EventArgs e) { Store store = this.CurrentGadgeteerDSLDocData.Store; if (store == null) { return; } Mainboard board = store.ElementDirectory.FindElements <Mainboard>().FirstOrDefault(); if (board == null) { return; } IEnumerable <Module> modules = store.ElementDirectory.FindElements <Module>(); using (var tx = store.TransactionManager.BeginTransaction()) { bool areModulesAlreadyConnected = board.Sockets.Any(s => s.SocketUse != null); //First try to move forward using the already existing connections var socketUses = from o in modules from su in o.SocketUses select su; bool success = AutoConnect.Solve(board, socketUses); string message = string.Empty; //If the above doesn't work, try again from scratch if (!success && areModulesAlreadyConnected) { //Disconnect all sockets and start over foreach (var socket in board.Sockets) { socket.Disconnect(); } success = AutoConnect.Solve(board, socketUses); } //3. Finally try with just the required sockets if (!success) { //Disconnect all sockets and start over foreach (var socket in board.Sockets) { socket.Disconnect(); } var requiredSocketUses = from su in socketUses where su.Optional == false select su; success = AutoConnect.Solve(board, requiredSocketUses); message = Resources.PackageUI.AutoConnectRequiredSockets; } if (success) { tx.Commit(); if (!string.IsNullOrEmpty(message)) { MessageBox.Show(message, Resources.PackageUI.ErrorDialogTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); } } else { MessageBox.Show(Resources.PackageUI.AutoConnectFailed, //message Resources.PackageUI.ErrorDialogTitle, //caption MessageBoxButtons.OK, MessageBoxIcon.Error); tx.Rollback(); } } }