WinForm in Components Contextmenu

menu
#1

Hey people,
happy easter and similar stuff… eggs and so on… yay?

Currently I try to use the components contextmenu to modify the behaviour of it. There are going to be a lot of different settings of different form and modi; so I tried to use WinForms, but I have some problems I do not understand at all… Putting basic controls, like radiobutton, into a container like Groupbox displays in weird way…

Can anybody tell me whats going on here with the containers (Panel / Groupbox).
What is needed to do to arrange the radiobuttons with a proper spacing, and fit the container to its childs?
I do not know a lot about WinForms. Normaly I do my UI’s with WPF or Eto…
I guess it would be the best choice to do all the stuff with the provided functions in DocumentObject.Menu_* but ya, there’nt a lot of them, so all the thing gets kind of messy.

I gues, Best would be to create some (nested) sub-menus… But ya, I havn’t found any method to do so… What is the way to go in this case?

Anyway.
I coded a simple class-definition to populate the contextmenu. If the basics are working I would like to add more/different combinations of controls.

public interface IMenuWatcher
{
	string Name { get; }
	void AppendMenu(ToolStripDropDown menu);
}


public sealed class MenuWatcher : IMenuWatcher
{
	public event SelectionChanged Changed;
	public delegate void SelectionChanged(MenuWatcher sender, int prevIndex);

	private string[] _entries;
	private int _selectedIndex;

	public MenuWatcher(string name, IEnumerable<string> entries)
	{
		_entries = entries.ToArray();

		Name = name;
	}

	public string SelectedEntry => this[SelectedIndex];
	public string this[int i] => _entries[i];


	public string Name { get; }

	public int SelectedIndex
	{
		get { return _selectedIndex; }
		set { Callback(this, new EventArgs(), value); }
	}

	public void AppendMenu(ToolStripDropDown menu)
	{
		GH_DocumentObject.Menu_AppendItem(menu, Name, (s, e) => { }, false);

		int idx = 0;
		foreach (string e in _entries)
		{
			int i = idx;

			RadioButton rd = new RadioButton() {Text = e};
			rd.CheckedChanged += (s, ev) => Callback(s, ev, i);
			rd.BackColor = Color.Transparent;

			GH_DocumentObject.Menu_AppendCustomItem(menu, rd);

			idx++;
		}

		GH_DocumentObject.Menu_AppendSeparator(menu);
	}

	[Obsolete("fishy display")]
	public void AppendMenu_Panel(ToolStripDropDown menu)
	{
		var grb = new Panel() { Text = Name };

		int idx = 0;
		foreach (string e in _entries)
		{
			int i = idx;

			RadioButton rd = new RadioButton() { Text = e };
			rd.CheckedChanged += (s, ev) => Callback(s, ev, i);
			rd.BackColor = Color.Transparent;

			grb.Controls.Add(rd);

			idx++;
		}

		GH_DocumentObject.Menu_AppendCustomItem(menu, grb);
	}

	[Obsolete("even a more fishy display")]
	public void AppendMenu_GroupBox(ToolStripDropDown menu)
	{
		var grb = new GroupBox() {Text = Name};

		int idx = 0;
		foreach (string e in _entries)
		{
			int i = idx;

			RadioButton rd = new RadioButton() { Text = e };
			rd.CheckedChanged += (s, ev) => Callback(s, ev, i);
			rd.BackColor = Color.Transparent;

			grb.Controls.Add(rd);

			idx++;
		}

		GH_DocumentObject.Menu_AppendCustomItem(menu, grb);
	}



	private void Callback(object sender, EventArgs args, int index)
	{
		if (_selectedIndex != index)
		{
			int prevIndex = _selectedIndex;
			_selectedIndex = index;

			Changed?.Invoke(this, prevIndex);
		}
	}
}

USED LIKE on a component…

(David Rutten) #2

All Grasshopper 1.0 UI is winforms based so if you want to add to it, that’s the platform you’ll need to target. However context menus are pretty volatile at the best of times, putting controls in them which have complicated interactions may not be the best idea. You could instead choose to display a form upon a menu click event. You can then choose either winforms, or WPF, or Eto, or…

I do have some utility methods for hosting controls inside winforms menus in GH, as I need them myself, and I may be able to get you an example tomorrow, but no guarantees it’ll ever be less than awkward to use.

#3

Thanks David for ur answer,

I allready changed to the approach u mentioned (showing a Form).
It gives me a better control over the display.

Anyway.
It would be nice to know how to add submenus to the ContextMenu with the existing Methods.
Can u tell me how to go on there? Without any WinForms in it, or any special things.

Greets
Mark

(David Rutten) #4

When you add a menu item using Menu_AppendItem(), you get back the menu item which was added. You can then start adding child items to that item for submenus.

#5

Is it possible to put these text boxes next to each other on one item line?
image
I’m overriding the AppendAdditionalMenuItem() and using the ToolStripTextBox class.

(David Rutten) #6

No, to achieve that you have to create a custom control with two textboxes and host that control in a menu container.