/// @brief Remove a plugin from the pin changed notify list. /// @details Only if the plugin exists on the list, this method removes from it. /// @param[in] plugin Compiled plugin reference to remove. public void RemoveOnPins(PluginCommon plugin) { if (PinHandlers.Contains(plugin)) { PinHandlers.Remove(plugin); } }
/// @brief Remove a plugin from the clock notify list. /// @details Only if the plugin exists on the list, this method removes from it. /// @param[in] plugin Compiled plugin reference to remove. public void RemoveOnClock(PluginCommon plugin) { if (TickHandlers.Contains(plugin)) { TickHandlers.Remove(plugin); } }
/// @brief Add a plugin to be notified on pin changes. /// @details It see if the plugin exist already to insert or not. /// @param[in] plugin Compiled plugin reference to include. public void NotifyOnPins(PluginCommon plugin) { if (!(PinHandlers.Contains(plugin))) { PinHandlers.Add(plugin); } }
/// @todo Document Gear.GUI.Emulator.documentsTab_KeyPress() /// private void documentsTab_KeyPress(object sender, KeyPressEventArgs e) { if (ActiveControl is PluginCommon) { PluginCommon b = ActiveControl as PluginCommon; if (b.AllowHotKeys != true) { return; } } if ((e.KeyChar == 's') | (e.KeyChar == 'S')) { if (runTimer.Enabled) { runTimer.Stop(); } else { stepInstruction_Click(sender, e); } } if ((e.KeyChar == 'r') | (e.KeyChar == 'R')) { if (!runTimer.Enabled) { runTimer.Start(); } } }
/// @brief Add a plugin to be notified on clock ticks. /// @details It see if the plugin exist already to insert or not. /// @param[in] plugin Compiled plugin reference to include. public void NotifyOnClock(PluginCommon plugin) { if (!(TickHandlers.Contains(plugin))) { TickHandlers.Add(plugin); } }
/// @brief Include a plugin to a propeller chip instance. /// @details Attach a plugin, linking the propeller instance to the plugin, opening a new /// tab window and enabling the close button by plugin's isClosable property. /// @param[in] plugin Instance of a Gear.PluginSupport.PluginCommon class to be attached. private void AttachPlugin(PluginCommon plugin) { if (plugin != null) { Chip.IncludePlugin(plugin); //include into plugin lists of a PropellerCPU instance #pragma warning disable 618 if (((PluginBaseV0_0.numInstances != 0) && (plugin is PluginBaseV0_0))) { ((PluginBaseV0_0)plugin).PresentChip(Chip);//invoke plugin old style way } #pragma warning restore 618 else { ((PluginBase)plugin).PresentChip(); //invoke plugin in modern way } TabPage t = new TabPage(plugin.Title); t.Parent = documentsTab; plugin.Dock = DockStyle.Fill; plugin.Parent = t; documentsTab.SelectedTab = t; //Maintain the close button availability if (plugin.IsClosable) { closeButton.Enabled = true; } else { closeButton.Enabled = false; } } }
/// @brief Delete a plugin from a propeller chip instance. /// @details Delete a plugin from the actives plugins of the propeller instance, /// effectively stopping the plugin. Remove also from pins and clock watch list. /// @param[in] plugin Instance of a Gear.PluginSupport.PluginCommon class to be detached. /// @since V15.03.26 - Added. //Added method to detach a plugin from the active plugin list of the propeller instance. private void DetachPlugin(PluginCommon plugin) { if (plugin.IsClosable) //check if the plugin is able to close, then remove... { Chip.RemoveOnPins(plugin); //from pins watch list Chip.RemoveOnClock(plugin); //from clock watch list Chip.RemovePlugin(plugin); //from the plugins registered to the propeller emulator } ; }
/// @brief Remove a plugin from the active plugin list of propeller instance /// @details Only if the plugin exists on the list, this method removes from it. /// Before detach, the `OnClose()` method of plugin is invoked, to do /// housekeeping, for example to clear pins managed by the plugin. /// @param[in] plugin Compiled plugin reference to remove public void RemovePlugin(PluginCommon plugin) { if (PlugIns.Contains(plugin)) { if (plugin is PluginBase) { //call the event before remove, but only for modern plugins ((PluginBase)plugin).OnClose(); } PlugIns.Remove(plugin); } }
/// @brief Determine availability of close plugin button when tab is changed. /// @details Enable close plugin button based on if active tab is subclass of /// Gear.PluginSupport.PluginCommon and if that class permit close the window. Typically /// the user plugins enabled it; but the cog window, main memory, logic probe, etc, /// don't allow to close. /// @param[in] sender Reference to object where event was raised. /// @param[in] e Event data arguments. /// @since V14.07.03 - Added. private void documentsTab_Click(object sender, EventArgs e) { TabPage tp = documentsTab.SelectedTab; if (tp.Controls[0] is PluginCommon) { PluginCommon b = (tp.Controls[0]) as PluginCommon; if (b.IsClosable) { closeButton.Enabled = true; } else { closeButton.Enabled = false; } } else { closeButton.Enabled = false; } }
/// @brief Include a plugin in active plugin list of propeller instance. /// @details It see if the plugin exist already to insert or not. /// @param[in] plugin Compiled plugin reference to include. public void IncludePlugin(PluginCommon plugin) { bool found = false; foreach (PluginCommon p in PlugIns) { if (p.Equals(plugin)) { found = true; break; } } // (!found | (found && !plugin.SingleInstanceAllowed)) is equivalent // to (!found | !plugin.SingleInstanceAllowed) if (!found | !plugin.SingleInstanceAllowed) { PlugIns.Add(plugin); } //if (!(PlugIns.Contains(plugin))) //{ // PlugIns.Add(plugin); //add to the list of plugins //} }
/// @brief Close the plugin window and terminate the plugin instance. /// @details Not only close the tab window, also detach the plugin from the PropellerCPU /// what uses it. /// @param[in] sender Reference to object where event was raised. /// @param[in] e Event data arguments. private void closeActiveTab_Click(object sender, EventArgs e) { TabPage tp = documentsTab.SelectedTab; PluginCommon p = (PluginCommon)tp.Controls[0]; if (p != null) //test if cast to PluginCommon works... { if (p.IsClosable) //... so, test if we can close the tab { if (documentsTab.SelectedIndex > 0) { //select the previous tab documentsTab.SelectedIndex = documentsTab.SelectedIndex - 1; //tab changing housekeeping for plugin close button documentsTab_Click(this, e); //detach the plugin from the emulator this.DetachPlugin(p); p.Dispose(); } tp.Parent = null; //delete the reference to plugin } ; } }
/// @brief Load a plugin from file. /// @details Try to open the XML definition for the plugin from the file name given as /// parameter. Then extract information from the XML (class name, auxiliary references /// and source code to compile), trying to compile the C# source code (based on /// Gear.PluginSupport.PluginCommon class) and returning the new class instance. If the /// compilation fails, then it opens the plugin editor to show errors and source code. /// @param[in] FileName Name and path to the XML plugin file to open /// @returns Reference to the new plugin instance (on success) or NULL (on fail). /// @throws Exception // TODO Modify the method to receive a PluginData, and delete the validation public void LoadPlugin(string FileName) { object objInst = null; //create the structure to fill data from file PluginData pluginCandidate = new PluginData(); //Determine if the XML is valid, and for which DTD version if (!pluginCandidate.ValidatePluginFile(FileName)) { string allMessages = string.Empty; //case not valid file, so show the errors. foreach (string strText in pluginCandidate.ValidationErrors) { allMessages += (strText.Trim() + "\r\n"); } /// @todo Add a custom dialog to show every error message in a grid. //show messages MessageBox.Show(allMessages, "Emulator - OpenPlugin.", MessageBoxButtons.OK, MessageBoxIcon.Error); } else //...XML plugin file is valid & system version is determined { //determine time to use to build the plugin DateTime TimeOfBuild = AssemblyUtils.GetFileDateTime(FileName); for (int i = 0; i < pluginCandidate.UseExtFiles.Length; i++) { if (pluginCandidate.UseExtFiles[i] == true) { TimeOfBuild = DateTime.FromBinary(Math.Max( TimeOfBuild.ToBinary(), AssemblyUtils.GetFileDateTime(pluginCandidate.ExtFiles[i]).ToBinary())); } } //generate the full name of the assembly corresponding to the plugin candidate string candidateAssemblyFullName = pluginCandidate.PluginAssemblyFullName(TimeOfBuild).FullName; //determine the version to look for the correct method to load it switch (pluginCandidate.PluginSystemVersion) { case "0.0": if (PluginPersistence.GetDataFromXML_v0_0(FileName, ref pluginCandidate)) { //Search and replace plugin class declarations for V0.0 plugin // system compatibility. pluginCandidate.Codes[0] = PluginSystem.ReplacePropellerClassV0_0( PluginSystem.ReplaceBaseClassV0_0(pluginCandidate.Codes[0])); } break; case "1.0": PluginPersistence.GetDataFromXML_v1_0(FileName, ref pluginCandidate); objInst = this.Chip; break; default: MessageBox.Show(string.Format("Plugin system version '{0}' not recognized " + "on file \"{1}\".", pluginCandidate.PluginSystemVersion, FileName), "Emulator - Open File.", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //add information into plugin's code to generate with assembly attributes pluginCandidate.Codes[0] = PluginSystem.InsertAssemblyDetails( pluginCandidate.Codes[0], TimeOfBuild, pluginCandidate.InstanceName, pluginCandidate.Description, pluginCandidate.PluginVersion); try { //Dynamic load and compile the plugin module as a class, giving the chip // instance as a parameter, and casting to appropriate class PluginCommon plugin = ModuleCompiler.LoadModule( pluginCandidate.Codes, //string[] codeTexts pluginCandidate.ExtFiles, //string[] sourceFiles pluginCandidate.InstanceName, //string module pluginCandidate.References, //string[] references objInst, //object objInstance pluginCandidate.PluginSystemVersion); //string pluginSystemVersion, if (plugin == null) { throw new Exception("Emulator - OpenPlugin: plugin object not generated!" + " (null response from memory loading)."); } else //if success compiling & instantiate the new instance... { //...add to the corresponding plugin list of the emulator instance AttachPlugin(plugin); //update location of last plugin Properties.Settings.Default.LastPlugin = FileName; Properties.Settings.Default.Save(); } } catch (Exception) { //open plugin editor in other window PluginEditor errorPlugin = new PluginEditor(false); if (errorPlugin.OpenFile(FileName, true)) { //remember plugin successfully loaded errorPlugin.UpdateLastPluginOpened(); //show plugin editor loaded with the faultly one errorPlugin.MdiParent = this.MdiParent; //the compilation errors are displayed in the error grid ModuleCompiler.EnumerateErrors(errorPlugin.EnumErrors); //show the error list errorPlugin.ShowErrorGrid(true); errorPlugin.Show(); } } } }