/// <summary> /// Generic construction of new MenuCommand instance. /// </summary> /// <param name="text">Display text for command.</param> /// <param name="imageList">Source for accessing command image.</param> /// <param name="imageIndex">Index into source ImageList.</param> /// <param name="shortcut">Keyboard combination to click command.</param> /// <param name="clickHandler">Handler for processing click event.</param> protected void InternalConstruct(string text, ImageList imageList, int imageIndex, Shortcut shortcut, EventHandler clickHandler) { // Save parameters _text = text; _imageList = imageList; _imageIndex = imageIndex; _shortcut = shortcut; _description = text; // This is not a clone _original = null; if (clickHandler != null) { Click += clickHandler; } // Define defaults for others _enabled = true; _checked = false; _radioCheck = false; _break = false; _tag = null; _visible = true; _infrequent = false; _image = null; // Create the collection of embedded menu commands _menuItems = new MenuCommandCollection(); }
/// <summary> /// Edits the specified object's value using the editor style indicated by GetEditStyle. /// </summary> /// <param name="context">An ITypeDescriptorContext that can be used to gain additional context information.</param> /// <param name="provider">An IServiceProvider that this editor can use to obtain services.</param> /// <param name="value">The object to edit.</param> /// <returns></returns> public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) { if ((context != null) && (context.Instance != null) && (provider != null)) { // Convert to the correct class. MenuCommandCollection commands = value as MenuCommandCollection; // Create the dialog used to edit the menu commands MenuCollectionDialog dialog = new MenuCollectionDialog(commands); // Give user the chance to modify the nodes if (dialog.ShowDialog() == DialogResult.OK) { // Reflect changes back into original copy and generate appropriate // component changes to designer to reflect these changes SynchronizeCollections(commands, dialog.Commands, context); // Notify container that value has been changed context.OnComponentChanged(); // Need to repaint the control to take account of new values MenuControl mc = context.Instance as MenuControl; // Just in case it is null if (mc != null) { mc.Invalidate(); } } } // Return the original value return(value); }
/// <summary> /// Initializes a new instance of the MenuCollectionDialog class. /// </summary> /// <param name="original">Original MenuCommand instances to be edited.</param> public MenuCollectionDialog(MenuCommandCollection original) { // Required for Windows Form Designer support InitializeComponent(); // Add menu commands to a node collection AddToNodeCollection(original, treeControl1.Nodes); // Set correct initial state of the buttons UpdateButtonState(); }
private void CommandsFromNodes(MenuCommandCollection commands, NodeCollection nodes) { // Process each tree node in turn foreach (Node n in nodes) { // Cast to correct type MenuCommand command = n.Tag as MenuCommand; // Add into the command collection commands.Add(command); // Remove any existing children command.MenuCommands.Clear(); // Populate with children CommandsFromNodes(command.MenuCommands, n.Nodes); } }
/// <summary> /// Dispose of resources. /// </summary> /// <param name="disposing">Disposing.</param> protected override void Dispose(bool disposing) { if (disposing) { // Must get rid of collections as they cache information if (_menuItems != null) { _menuItems.Dispose(); _menuItems = null; } if (_original != null) { _original.Dispose(); _original = null; } } base.Dispose(disposing); }
private void AddToNodeCollection(MenuCommandCollection commands, NodeCollection nodes) { // Add each command in turn foreach (MenuCommand command in commands) { string text = command.Text; // Use a string to make it easier to select a node if (text.Length == 0) { text = "<Empty>"; } else if (text.Equals("-")) { text = "(Separator)"; } // Create a node to represent the command Node n = new Node(text); // Attach a copy of the menu command to the node instance n.Tag = command.Clone(); // Add to end of the node collection nodes.Add(n); // Get access to the copy of the original MenuCommand clone = n.Tag as MenuCommand; // We want to know whenever the menu text is changed clone.PropertyChanged += new Crownwood.DotNetMagic.Menus.MenuCommand.PropChangeHandler(OnPropertyChanged); // Add any child commands AddToNodeCollection(command.MenuCommands, n.Nodes); } }
private void SynchronizeCollections(MenuCommandCollection orig, MenuCommandCollection copy, ITypeDescriptorContext context) { // Make a note of all original commands that are still in copy Hashtable both = new Hashtable(); // First pass, scan looking for nodes that are in original and copy foreach (MenuCommand copyChild in copy) { // Does this node have an back pointer to its original? if (copyChild.Original != null) { // Then make a note that it is in both collections both.Add(copyChild.Original, copyChild.Original); // Update the original from the copy copyChild.Original.UpdateInstance(copyChild); } } int origCount = orig.Count; // Second pass, remove commands in the original but not in the copy for (int i = 0; i < origCount; i++) { // Get access to the indexed command from original MenuCommand origChild = orig[i]; // If not in the found collection... if (!both.ContainsKey(origChild)) { // ...then it has been removed from the copy, so delete it orig.Remove(origChild); // Must remove from context container so it is removed from designer tray context.Container.Remove(origChild as IComponent); // Must also remove everything below the command RemoveAllChildren(origChild, context); // Reduce the count and index to reflect change in collection contents --i; --origCount; } } int copyCount = copy.Count; // Third pass, add new commands from copy but not in original for (int i = 0; i < copyCount; i++) { // Get access to the indexed node from copy MenuCommand copyChild = copy[i]; // If this command is a new one then it will not have an 'original' property if (copyChild.Original == null) { // Add this node into the original at indexed position orig.Insert(i, copyChild); // It references itself in the new collection copyChild.Original = copyChild; // Must add into context container so it is added to the designer tray context.Container.Add(copyChild as IComponent); // Must also add everything below the command AddAllChildren(copyChild, context); } } // Fourth pass, set correct ordering to match copy for (int i = 0; i < copyCount; i++) { // Grab indexed item from the copy MenuCommand copyChild = copy[i]; // Get the command to look for in original MenuCommand origChild = copyChild.Original; // Find its indexed position in original collection int origIndex = orig.IndexOf(origChild); // If this is not its required position if (origIndex != i) { // Remove it from collection orig.Remove(origChild); // Insert back in correct place orig.Insert(i, origChild); } } // Fifth pass, process all children foreach (MenuCommand copyChild in copy) { // Does this node has an back pointer to its original? if (copyChild.Original != null) { // Recurse down into the child collections SynchronizeCollections(copyChild.Original.MenuCommands, copyChild.MenuCommands, context); } } }