#region Disclaimer / License
// Copyright (C) 2011, Jackie Ng
// http://trac.osgeo.org/mapguide/wiki/maestro, jumpinjackie@gmail.com
//
// This library 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 2.1 of the License, or (at your option) any later version.
//
// This library 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 this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion Disclaimer / License
using OSGeo.MapGuide.MaestroAPI;
using OSGeo.MapGuide.ObjectModels;
using OSGeo.MapGuide.ObjectModels.SymbolDefinition;
using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
namespace Maestro.Editors.SymbolDefinition
{
///
/// A UI control for editing symbol definition settings
///
[ToolboxItem(true)]
[Designer(typeof(SymbolFieldDesigner))]
public partial class SymbolField : UserControl
{
private class SymbolFieldDesigner : ControlDesigner
{
public override IList SnapLines
{
get
{
/* Code from above */
IList snapLines = base.SnapLines;
// *** This will need to be modified to match your user control
SymbolField control = Control as SymbolField;
if (control == null) { return snapLines; }
Control el = control.combo;
if (el == null) { return snapLines; }
// *** This will need to be modified to match the item in your user control
// This is the control in your UC that you want SnapLines for the entire UC
IDesigner designer = TypeDescriptor.CreateDesigner(
el, typeof(IDesigner));
if (designer == null) { return snapLines; }
// *** This will need to be modified to match the item in your user control
designer.Initialize(el);
using (designer)
{
ControlDesigner boxDesigner = designer as ControlDesigner;
if (boxDesigner == null) { return snapLines; }
foreach (SnapLine line in boxDesigner.SnapLines)
{
if (line.SnapLineType == SnapLineType.Baseline)
{
// *** This will need to be modified to match the item in your user control
snapLines.Add(new SnapLine(SnapLineType.Baseline,
line.Offset + el.Top,
line.Filter, line.Priority));
break;
}
}
}
return snapLines;
}
}
}
///
/// A method for presenting symbol parameters for a given symbol field
///
/// The sender.
public delegate void BrowseEventHandler(SymbolField sender);
///
/// Occurs when a request has been made to present symbol parameters for selection
///
public event BrowseEventHandler RequestBrowse;
///
/// Initializes a new instance of the class.
///
public SymbolField()
{
InitializeComponent();
combo.TextChanged += new EventHandler(combo_TextChanged);
}
private void combo_TextChanged(object sender, EventArgs e)
{
OnContentChanged();
}
///
/// Occurs when [content changed].
///
public event EventHandler ContentChanged;
//Important: We need to set this otherwise the Winforms Designer will put you in a world of pain
///
/// Gets or sets the content.
///
///
/// The content.
///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Content
{
get { return combo.Text; }
set
{
if (combo.Text != value)
{
combo.Text = value;
OnContentChanged();
}
}
}
///
/// Gets or sets the enum type. Only set this if the underlying symbol property is an enum type
///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Type EnumType
{
get;
private set;
}
///
/// Sets this field to explicitly take enum values for input
///
///
public void SetEnumMode()
{
this.EnumType = typeof(TEnum);
this.Items = GetItems(false);
combo.DropDownStyle = ComboBoxStyle.DropDownList;
}
///
/// Sets this field for boolean input
///
public void SetBooleanMode()
{
this.EnumType = null;
this.Items = new string[]
{
true.ToString().ToLower(),
false.ToString().ToLower()
};
}
private void OnContentChanged()
{
if (_isBinding)
return;
if (_suppressProperty)
return;
//Update databound property before raising event
if (_boundObjectType != null && _boundObject != null && _boundProperty != null)
{
try
{
_suppressUI = true;
if (string.IsNullOrEmpty(this.Content))
{
_boundProperty.SetValue(_boundObject, null, null);
}
else
{
if (this.EnumType != null)
{
_boundProperty.SetValue(_boundObject, Enum.Parse(this.EnumType, this.Content), null);
}
else
{
_boundProperty.SetValue(_boundObject, this.Content, null);
}
}
}
finally
{
_suppressUI = false;
}
}
var handler = this.ContentChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
private string[] _items;
//Important: We need to set this otherwise the Winforms Designer will put you in a world of pain
///
/// Gets or sets the items.
///
///
/// The items.
///
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string[] Items
{
get { return _items; }
set
{
_items = value;
combo.Items.Clear();
foreach (var it in value)
{
combo.Items.Add(it);
}
}
}
private void btnBrowse_Click(object sender, EventArgs e)
{
var handler = this.RequestBrowse;
if (handler != null)
handler(this);
}
//Important: We need to set this otherwise the Winforms Designer will put you in a world of pain
//[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
//[Description("Indicates the parameter data type(s) that are suitable for this field. Leave empty for all types")]
//public DataType[] SupportedDataTypes { get; set; }
//Important: We need to set this otherwise the Winforms Designer will put you in a world of pain
//[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
///
/// Gets or sets the supported enhanced data types.
///
///
/// The supported enhanced data types.
///
[Description("Indicates the parameter data type(s) that are suitable for this field. Leave empty for all types")]
public DataType2[] SupportedEnhancedDataTypes { get; set; }
///
/// Gets the items
///
///
///
public static string[] GetItems()
{
return GetItems(true);
}
///
/// Gets the items.
///
///
///
public static string[] GetItems(bool quote)
{
var values = Enum.GetValues(typeof(T));
var items = new string[values.Length];
int i = 0;
if (quote)
{
foreach (var val in values)
{
items[i] = "'" + val + "'";
i++;
}
}
else
{
foreach (var val in values)
{
items[i] = val + "";
i++;
}
}
return items;
}
//This code below attempts to approximate data binding
private bool _suppressUI = false; //Used to prevent a stack overflow due to a continuous UI -> Property -> UI -> ... chain
private bool _suppressProperty = false; //Used to prevent a stack overflow due to a continuous UI -> Property -> UI -> ... chain
private bool _isBinding = false;
private object _boundObject;
private Type _boundObjectType;
private PropertyInfo _boundProperty;
///
/// Binds the specified data source.
///
/// The data source.
/// Name of the property.
public void Bind(object dataSource, string propertyName)
{
Check.ArgumentNotNull(dataSource, nameof(dataSource));
Check.ArgumentNotEmpty(propertyName, nameof(propertyName));
try
{
_isBinding = true;
if (_boundObject != null)
{
var i = _boundObject as INotifyPropertyChanged;
if (i != null)
i.PropertyChanged -= OnBoundObjectPropertyChanged;
}
_boundObject = dataSource;
_boundObjectType = _boundObject.GetType();
_boundProperty = _boundObjectType.GetProperty(propertyName);
if (_boundProperty == null)
throw new InvalidOperationException("Could not find property " + _boundProperty + " of databound object (" + _boundObjectType.Name + ")"); //LOCALIZEME
//Set initial value
var val = _boundProperty.GetValue(_boundObject, null);
if (val != null)
this.Content = val.ToString();
else
this.Content = null;
var inp = _boundObject as INotifyPropertyChanged;
if (inp != null)
{
inp.PropertyChanged += WeakEventHandler.Wrap(OnBoundObjectPropertyChanged, (eh) => inp.PropertyChanged -= eh);
}
}
finally
{
_isBinding = false;
}
}
private void OnBoundObjectPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (_isBinding)
return;
if (_suppressUI)
return;
if (_boundProperty.Name != e.PropertyName)
return;
try
{
_suppressProperty = true;
var val = _boundProperty.GetValue(_boundObject, null);
if (val != null)
this.Content = val.ToString();
else
this.Content = null;
}
finally
{
_suppressProperty = false;
}
}
}
}