#region "SoapBox.Core License"
///
/// Copyright (C) 2009 SoapBox Automation Inc., All Rights Reserved.
/// Contact: SoapBox Automation Licencing (license@soapboxautomation.com)
///
/// This file is part of SoapBox Core.
///
/// Commercial Usage
/// Licensees holding valid SoapBox Automation Commercial licenses may use
/// this file in accordance with the SoapBox Automation Commercial License
/// Agreement provided with the Software or, alternatively, in accordance
/// with the terms contained in a written agreement between you and
/// SoapBox Automation Inc.
///
/// GNU Lesser General Public License Usage
/// SoapBox Core is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Lesser General Public License
/// as published by the Free Software Foundation, either version 3 of the
/// License, or (at your option) any later version.
///
/// SoapBox Core is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU Lesser General Public License for more details.
///
/// You should have received a copy of the GNU Lesser General Public License
/// along with SoapBox Core. If not, see .
///
#endregion
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Windows.Media;
using SoapBox.Utilities;
namespace SoapBox.Core
{
public abstract class AbstractMenuItem
: AbstractCommandControl, IMenuItem
{
[System.Runtime.InteropServices.DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
public AbstractMenuItem()
: base()
{
VisibleCondition = new MenuItemVisibleCondition(this);
CanExecuteChanged += delegate
{
if (IconFull != null)
{
NotifyPropertyChanged(m_IconArgs);
}
};
}
#region " IMenuItem Implementation "
#region " Header "
///
/// This is the text displayed in the menu item itself.
/// Use the _ (underscore) notation to specify shortcut keys.
/// For instance: "_File".
/// Best to set this property in the derived class's constructor.
///
public string Header
{
get
{
return m_Header;
}
protected set
{
if (value == null)
{
throw new ArgumentNullException();
}
if (m_Header != value)
{
m_Header = value;
NotifyPropertyChanged(m_HeaderArgs);
}
}
}
private string m_Header = string.Empty;
static readonly PropertyChangedEventArgs m_HeaderArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.Header);
#endregion
#region " Items "
///
/// If the menu item being defined has a submenu, then replace this
/// with a collection of the menu items in the submenu.
///
public IEnumerable Items
{
get
{
return m_Items;
}
protected set
{
if (m_Items != value)
{
m_Items = value;
NotifyPropertyChanged(m_ItemsArgs);
}
}
}
private IEnumerable m_Items = null;
static readonly PropertyChangedEventArgs m_ItemsArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.Items);
#endregion
#region " Icon "
///
/// Optional icon that can be displayed in the button.
///
public object Icon
{
get
{
if (IconFull != null)
{
System.Windows.Controls.Image img = new System.Windows.Controls.Image();
if (EnableCondition.Condition)
{
img.Source = IconFull;
}
else
{
img.Source = IconGray;
}
return img;
}
else
{
return null;
}
}
}
private BitmapSource IconFull
{
get
{
return m_IconFull;
}
set
{
if (m_IconFull != value)
{
m_IconFull = value;
if (m_IconFull != null)
{
IconGray = ConvertFullToGray(m_IconFull);
}
else
{
IconGray = null;
}
NotifyPropertyChanged(m_IconArgs);
}
}
}
private BitmapSource m_IconFull = null;
static readonly PropertyChangedEventArgs m_IconArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.Icon);
private BitmapSource IconGray { get; set; }
private BitmapSource ConvertFullToGray(BitmapSource full)
{
FormatConvertedBitmap gray = new FormatConvertedBitmap();
gray.BeginInit();
gray.Source = full;
gray.DestinationFormat = PixelFormats.Gray32Float;
gray.EndInit();
return gray;
}
///
/// This is a helper function so you can assign the Icon directly
/// from a Bitmap, such as one from a resources file.
///
///
protected void SetIconFromBitmap(System.Drawing.Bitmap value)
{
if (value == null) throw new ArgumentNullException();
IntPtr hBitmap = value.GetHbitmap();
try
{
BitmapSource b = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
IconFull = b;
}
finally
{
DeleteObject(hBitmap);
}
}
#endregion
#region " IsCheckable "
///
/// By default this is false. Set it to true in the constructor of the
/// derived class to turn this menu item into a checkable item.
/// Then override OnIsCheckedChanged and check the IsChecked property
/// in the derived class to react when the user checks or unchecks it.
///
public bool IsCheckable
{
get
{
return m_IsCheckable;
}
protected set
{
if (m_IsCheckable != value)
{
m_IsCheckable = value;
NotifyPropertyChanged(m_IsCheckableArgs);
}
}
}
private bool m_IsCheckable = false;
static readonly PropertyChangedEventArgs m_IsCheckableArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.IsCheckable);
#endregion
#region " IsChecked "
///
/// True if the item is checked, false otherwise.
/// Calls OnIsCheckedChanged(), which can be overridden in the
/// derived class to take an action when the status
/// is toggled.
///
public bool IsChecked
{
get
{
return m_IsChecked;
}
set
{
if (m_IsChecked != value)
{
m_IsChecked = value;
NotifyPropertyChanged(m_IsCheckedArgs);
OnIsCheckedChanged();
}
}
}
private bool m_IsChecked = false;
static readonly PropertyChangedEventArgs m_IsCheckedArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.IsChecked);
///
/// This method is called only if IsCheckable is true and
/// the user changes the IsChecked property. Override it in
/// the derived class to take an action when it changes.
///
protected virtual void OnIsCheckedChanged() { }
#endregion
#region " IsSeparator "
///
/// Defaults to false. Set to true in the constructor to make this a
/// separator instead of a menu item.
///
public bool IsSeparator
{
get
{
return m_IsSeparator;
}
protected set
{
if (m_IsSeparator != value)
{
m_IsSeparator = value;
NotifyPropertyChanged(m_IsSeparatorArgs);
}
}
}
private bool m_IsSeparator = false;
static readonly PropertyChangedEventArgs m_IsSeparatorArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.IsSeparator);
#endregion
#region " Context "
///
/// In a context menu, this can be set to the ViewModel of the item
/// that was clicked on to open the ContextMenu. Needs some hooking
/// up in the xaml though (hint: handle the ContextMenuOpening event
/// on the control that the ContextMenu is attached to).
/// Note that setting this property will set the Context property
/// on all child menu items (following the Items collection property).
///
public object Context
{
get
{
return m_Context;
}
set
{
if (m_Context != value)
{
m_Context = value;
if (Items != null)
{
foreach (IMenuItem item in Items)
{
item.Context = m_Context;
}
}
NotifyPropertyChanged(m_ContextArgs);
}
}
}
private object m_Context = null;
static readonly PropertyChangedEventArgs m_ContextArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.Context);
#endregion
#region " IsSubmenuOpen "
public bool IsSubmenuOpen
{
get
{
return m_IsSubmenuOpen;
}
set
{
if (m_IsSubmenuOpen != value)
{
m_IsSubmenuOpen = value;
NotifyPropertyChanged(m_IsSubmenuOpenArgs);
OnIsSubmenuOpenChanged();
}
}
}
private bool m_IsSubmenuOpen = false;
private static readonly PropertyChangedEventArgs m_IsSubmenuOpenArgs =
NotifyPropertyChangedHelper.CreateArgs(o => o.IsSubmenuOpen);
private static string m_IsSubmenuOpenName =
NotifyPropertyChangedHelper.GetPropertyName(o => o.IsSubmenuOpen);
///
/// This method is called only if
/// the user changes the IsSubmenuOpen property. Override it in
/// the derived class to take an action when it changes.
///
protected virtual void OnIsSubmenuOpenChanged() { }
#endregion
#endregion
}
}