GenericMenuExtensions

Description
This editor script defines extension methods for Unity's GenericMenu class which aim to reduce the amount of code clutter when building menus.

The source code on this page is released under the MIT license.

Assets/Editor/GenericMenuExtensions.cs
///    /// The menu that is being constructed. /// Content of menu item. ///    /// Context object used whilst adding a menu item. ///    ///  ///    /// If is a value of null. /// If is a value of null. ///    ///     public static IGenericMenuAddItemContext AddItem(this GenericMenu menu, GUIContent content) { if (menu == null) throw new ArgumentNullException("menu"); if (content == null) throw new ArgumentNullException("content");

return GenericMenuAddItemContext.GetContext(menu, content); }

///    /// Begin adding an item to the . ///    ///     /// Here are some usage examples: ///     ///     /// The menu that is being constructed. /// Text of menu item. ///    /// Context object used whilst adding a menu item. ///    ///  ///    /// If is a value of null. /// If is a value of null. ///    ///     ///  /// If is an empty string. ///    public static IGenericMenuAddItemContext AddItem(this GenericMenu menu, string text) { if (menu == null) throw new ArgumentNullException("menu"); if (text == null) throw new ArgumentNullException("text"); if (text == "") throw new ArgumentException("Empty string.", "text");

return GenericMenuAddItemContext.GetContext(menu, GetContent(text)); }

///    /// Adds separator to the . ///    /// The menu that is being constructed. ///  /// If is a value of null. ///    public static void AddSeparator(this GenericMenu menu) { if (menu == null) throw new ArgumentNullException("menu");

menu.AddSeparator(""); }

}

/// /// Describes current context of adding an item to a <see cref="GenericMenu"/>. /// /// <seealso cref="GenericMenuExtensions.AddItem(GenericMenu, GUIContent)"/> /// <seealso cref="GenericMenuExtensions.AddItem(GenericMenu, string)"/> public interface IGenericMenuAddItemContext {

///    /// Specifies whether menu item should be enabled. ///    ///     ///      ///     /// Specifies whether item is enabled. ///    /// The <see cref="IGenericMenuAddItemContext"/> instance for chained method calls. ///    IGenericMenuAddItemContext Enable(bool enable);

///    /// Specifies whether menu item should be enabled. ///    ///     ///      ///     /// Predicate that determines whether item is enabled by    /// by returning a value of true</c>. ///    /// The <see cref="IGenericMenuAddItemContext"/> instance for chained method calls. ///    /// <exception cref="System.ArgumentNullException"> /// If is a value of null</c>. ///    IGenericMenuAddItemContext Enable(Func predicate);

///    /// Specifies whether menu item should be visible in menu. ///    ///     ///      ///     /// Specifies whether item is visible. ///    /// The <see cref="IGenericMenuAddItemContext"/> instance for chained method calls. ///    IGenericMenuAddItemContext Visible(bool visible);

///    /// Specifies whether menu item should be visible. ///    ///     ///      ///     /// Predicate that determines whether item is visible by    /// returning a value of true</c>. ///    /// The <see cref="IGenericMenuAddItemContext"/> instance for chained method calls. ///    /// <exception cref="System.ArgumentNullException"> /// If is a value of null</c>. ///    IGenericMenuAddItemContext Visible(Func predicate);

///    /// Specifies whether menu item should be in an "on" state (aka checked). ///    ///     ///      ///     /// Indicates if menu item is "on". ///    /// The <see cref="IGenericMenuAddItemContext"/> instance for chained method calls. ///    IGenericMenuAddItemContext On(bool on);

///    /// Specifies whether menu item should be in an "on" state (aka checked). ///    ///     ///      ///     /// Predicate that determines whether item is "on" by    /// returning a value of true</c>. ///    /// The <see cref="IGenericMenuAddItemContext"/> instance for chained method calls. ///    /// <exception cref="System.ArgumentNullException"> /// If is a value of null</c>. ///    IGenericMenuAddItemContext On(Func predicate);

///    /// Finalize addition of menu item by assigning an action to it. ///    ///     ///      ///     /// Delegate to perform menu action. /// <exception cref="System.ArgumentNullException"> /// If is a value of null</c>. ///    void Action(GenericMenu.MenuFunction action);

///    /// Finalize addition of menu item by assigning an action to it. ///    ///     ///      ///     /// Delegate to perform menu action. /// <param name="userData">Additional data that is made available to menu action. /// <exception cref="System.ArgumentNullException"> /// If is a value of null</c>. ///    void Action(GenericMenu.MenuFunction2 action, object userData);

}

internal sealed class GenericMenuAddItemContext : IGenericMenuAddItemContext {

private static Stack<GenericMenuAddItemContext> s_Pool = new Stack<GenericMenuAddItemContext>;

public static GenericMenuAddItemContext GetContext(GenericMenu menu, GUIContent content) { var context = s_Pool.Count > 0 ? s_Pool.Pop : new GenericMenuAddItemContext;

context._menu = menu; context._content = content; context._visible = true; context._enabled = true; context._on = false;

return context; }

private static void ReturnContext(GenericMenuAddItemContext context) { context._menu = null; context._content = null;

s_Pool.Push(context); }

private GenericMenu _menu; private GUIContent _content; private bool _visible; private bool _enabled; private bool _on;

#region IGenericMenuAddItemContext Members

public IGenericMenuAddItemContext Enable(bool enable) { _enabled = enable; return this; }

public IGenericMenuAddItemContext Enable(Func predicate) { if (predicate == null) throw new ArgumentNullException("predicate");

_enabled = predicate; return this; }

public IGenericMenuAddItemContext Visible(bool visible) { _visible = visible; return this; }

public IGenericMenuAddItemContext Visible(Func predicate) { if (predicate == null) throw new ArgumentNullException("predicate");

_visible = predicate; return this; }

public IGenericMenuAddItemContext On(bool on) { _on = on; return this; }

public IGenericMenuAddItemContext On(Func predicate) { if (predicate == null) throw new ArgumentNullException("predicate");

_on = predicate; return this; }

public void Action(GenericMenu.MenuFunction action) { try { if (action == null) throw new ArgumentNullException("action");

if (!_visible) return; if (_enabled) _menu.AddItem(_content, _on, action); else _menu.AddDisabledItem(_content); }       finally { ReturnContext(this); }   }

public void Action(GenericMenu.MenuFunction2 action, object userData) { try { if (action == null) throw new ArgumentNullException("action");

if (!_visible) return; if (_enabled) _menu.AddItem(_content, _on, action, userData); else _menu.AddDisabledItem(_content); }       finally { ReturnContext(this); }   }

#endregion

}

License
The MIT License (MIT)

Copyright (c) 2014 Rotorz Limited

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

-- End of License --