using System;
using System.Windows.Forms;
using System.Collections;
using System.Drawing;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Ironring.MMC.Core;
using Ironring.MMC.Nodes;
namespace Ironring.MMC.PropertyPages{
//Added by Alexander Kachalkov
/// <summary>
/// For Invoke method when marshaling from PropertySheet thread
/// </summary>
public delegate void OnUserDelegate(string key, object val);
#region PropertySheet
/// <summary>
/// This implements the equivalent of a Win32 PropertySheet
/// </summary>
public class PropertySheet : Form
{
private OnUserDelegate _closeHandle = null;
//Added by Alexander Ovchinnikov for close PS after remove node
/// <summary>
///
/// </summary>
protected ResultViewItem m_resultviewitem;
///////////////////////////////////////////////////////////////////////
//
// Private vars
//
#region
private Button _btnOk = new Button();
private Button _btnCancel = new Button();
private Button _btnApply = new Button();
private PropertySheetTabControl _tc;
private PropertyPageList _allPages = new PropertyPageList();
private bool _fClosed;
private BaseNode _parentNode;
#endregion
///////////////////////////////////////////////////////////////////////
//
// Properties
//
#region Properties
//[--added by Harald Binkle (tigerharry)
/// <summary>
/// Apply button at the buttomn of the propertypage. Set to null if should not be added.
/// </summary>
public Button BtnApply
{
get { return _btnApply; }
set { _btnApply = value; }
}
/// <summary>
/// Cancel button at the buttomn of the propertypage. Set to null if should not be added.
/// </summary>
public Button BtnCancel
{
get { return _btnCancel; }
set { _btnCancel = value; }
}
/// <summary>
/// OK button at the buttomn of the propertypage
/// </summary>
public Button BtnOk
{
get { return _btnOk; }
set { _btnOk = value; }
}
//--]
/// <summary>
/// Get the item we are a property page for.
/// </summary>
public ResultViewItem ResultViewItem
{
get { return this.m_resultviewitem; }
}
/// <summary>
/// Get the Typed pages collection we display
/// </summary>
public PropertyPageList Pages
{
get{ return _allPages; }
}
/// <summary>
/// get the Tab control
/// </summary>
public PropertySheetTabControl Tabs
{
get{ return _tc; }
}
/// <summary>
/// get the node this propertysheet represents
/// </summary>
public BaseNode Node
{
get { return _parentNode; }
}
/// <summary>
/// returns if the fake closed flag is enabled i.e. is the form hidden?
/// </summary>
public bool isClosed
{
get { return _fClosed; }
}
// Added by Lesley van Zijl
/// <summary>
/// Ask for the state of the ApplyButton
/// </summary>
/// <returns></returns>
public bool IsApplyEnabled()
{
//changed by Harald Binkle (tigerharry)
return _btnApply != null ? _btnApply.Enabled : false;
}
/// <summary>
/// Returns the closehandle
/// </summary>
public OnUserDelegate CloseHandle
{
get { return _closeHandle; }
}
#endregion
/// <summary>
/// Construct provides linkage to the snapin node
/// </summary>
/// <param name="node"></param>
public PropertySheet(BaseNode node)
{
_parentNode = node;
// Make sure nobody can resize this form
FormBorderStyle = FormBorderStyle.FixedDialog;
Icon = null;
ShowInTaskbar = false;
MaximizeBox = false;
MinimizeBox = false;
_fClosed = false;
//Added by Alexander Kachalkov
//This call is required by the Windows Form Designer.
InitializeComponent();
//Added by Alexander Ovchinnikov for close PS after remove node
//initialise closeDelegate
if( _closeHandle == null )
{
_closeHandle += new OnUserDelegate( ClosePropertySheet );
}
}
/// <summary>
/// Prepares the property sheet to be shown and then displays it
/// </summary>
public new DialogResult ShowDialog()
{
Controls.Clear();
// Figure out how big to make the tab control
// by sizing to the largest UserControl
int nWidth = 240;
int nHeight = 0;
// We'll be as wide as the widest and tall as the tallest page
foreach (PropertyPage page in _allPages)
{
// Initialize the Property Pages
page.PropertySheet = this;
if (page.Size.Width > nWidth)
nWidth = page.Size.Width;
if (page.Size.Height> nHeight)
nHeight = page.Size.Height;
}
// Tab Control should be on the top...
_tc = new PropertySheetTabControl();
// Add the pages to the sheet
foreach (PropertyPage page in _allPages)
{
// Create a Tab page that we can use
_tc.TabPages.Add(page.CreateTabPage());
}
// Add the height of the tab thingy and the indentation
_tc.Location = new Point(4, 5);
_tc.SelectedIndexChanging += new CheckValidation(OnTabPageChanged);
_tc.TabIndex = 0;
Controls.Add(_tc);
// Adjust the height of of the tab control to account for the
// margin and the tabs up top.
// We need to do this so the Tab Control gets created on the Win32 side of
// things, which makes m_tc.ItemSize.Height valid.
IntPtr handle = _tc.Handle;
nHeight += _tc.Location.Y + _tc.ItemSize.Height;
// calculate the tabcontrol height
_tc.Size = new System.Drawing.Size(nWidth, nHeight);
nHeight = CalcTabHeight(nHeight);
_tc.Size = new System.Drawing.Size(nWidth, nHeight);
// We'll have a 15 pixel buffer between the tab control and the buttons
nHeight += 15;
// Now put the Ok, Cancel, and Apply buttons on the page.
//[--added if(!=null), nextBtnPos and space by Harald Binkle (tigerharry)
int nextBtnPos = nWidth;
int space = +4;
if (_btnApply != null)
{
_btnApply.Size = new System.Drawing.Size(75, 23);
_btnApply.Location = new Point(nextBtnPos - _btnApply.Width + space, nHeight);
space = -space;
nextBtnPos = _btnApply.Location.X;
_btnApply.Text = SnapinBase.Translate("Apply");
_btnApply.Enabled = false;
_btnApply.TabIndex = 3;
_btnApply.Click += new EventHandler(OnApplyClick);
//Added by Alexander Kachalkov
_btnApply.FlatStyle = FlatStyle.System;
Controls.Add(_btnApply);
}
if (_btnCancel != null)
{
_btnCancel.Size = new System.Drawing.Size(75, 23);
_btnCancel.Location = new Point(nextBtnPos - _btnCancel.Width + space, nHeight);
space = -Math.Abs(space);
nextBtnPos = _btnCancel.Location.X;
_btnCancel.Text = SnapinBase.Translate("Cancel");
_btnCancel.Click += new EventHandler(OnCancelClick);
_btnCancel.TabIndex = 2;
//Added by Alexander Kachalkov
_btnCancel.FlatStyle = FlatStyle.System;
Controls.Add(_btnCancel);
}
_btnOk.Size = new System.Drawing.Size(75, 23);
_btnOk.Location = new Point(nextBtnPos - _btnOk.Width + space, nHeight);
_btnOk.Text = SnapinBase.Translate("Ok");
_btnOk.TabIndex = 1;
_btnOk.Click += new EventHandler(OnOkClick);
//Added by Alexander Kachalkov
_btnOk.FlatStyle = FlatStyle.System;
Controls.Add(_btnOk);
//--]
// Make sure we account for the height of the button
nHeight += _btnOk.Height;
// We have a 4 pixel margin on each side of the tab control, and a 5 pixel margin
// between the buttons and the bottom of the page
ClientSize = new System.Drawing.Size(nWidth + 8, nHeight + 5);
this.AcceptButton = _btnOk;
this.CancelButton = _btnCancel;
//Added by Alexander Kachalkov
base.Closing += new CancelEventHandler(OnCloseClick);
// And finally, make us actually show
return base.ShowDialog();
}
/// <summary>
/// Fix by Pietro Di Gregorio
/// Calculation of the tabcontrol size to allow a multiline display of the tabs
/// </summary>
/// <param name="origHeight">Height before calculation</param>
/// <returns>The multilined heigth</returns>
private int CalcTabHeight(int origHeight)
{
int before = _tc.TabPages[0].Size.Height;
_tc.Multiline = true;
_tc.SizeMode = TabSizeMode.FillToRight;
return origHeight += (before - _tc.TabPages[0].Size.Height);
}
///////////////////////////////////////////////////////////////////////
//
// Events
//
#region
//Added by Attila Kapostyak
/// <summary>
/// Event handler that pops up when the user tries to
/// change property pages. Make sure that the data on the
/// page they're leaving is correct.
/// </summary>
/// <returns></returns>
bool OnTabPageChanged()
{
bool isValidData;
PropertyPage page = _allPages[_tc.SelectedIndex];
isValidData = page.ValidateData();
if (isValidData)
{
foreach(PropertyPage pages in _allPages)
pages.TabChange();
}
return isValidData;
}
//Added by Alexander Kachalkov
//to be able to show form again after closing it
void OnCloseClick(Object o, CancelEventArgs e)
{
Node.EditMode = false;
e.Cancel = false;
// this one is not needed, double, made the DialogResult go poof.
//onCancelClick(o, e);
}
/// <summary>
/// The user clicked ok. Treat it as an Apply, and then close the page
/// </summary>
/// <param name="o"></param>
/// <param name="e"></param>
void OnOkClick(Object o, EventArgs e)
{
PropertyPage page = _allPages[_tc.SelectedIndex];
if (page.ValidateData())
{
//Added by Alexander Kachalkov
base.DialogResult = DialogResult.OK;
OnApplyClick(o, e);
FakeClose();
}
}
/// <summary>
/// The user clicked cancel.
/// </summary>
/// <param name="o"></param>
/// <param name="e"></param>
void OnCancelClick(Object o, EventArgs e)
{
if(IsApplyEnabled() == true && PropertyPageSettings.Instance.UseCancelDialogs == true)
{
switch(MessageBox.Show(SnapinBase.Translate("OnCancelWarningText"),
SnapinBase.Translate("OnCancelWarningTitle"),
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning))
{
case DialogResult.Yes:
OnApplyClick(o, e);
break;
case DialogResult.Cancel:
base.DialogResult = DialogResult.None;
break;
default:
base.DialogResult = DialogResult.Cancel;
foreach(PropertyPage page in _allPages)
page.onCancel();
FakeClose();
break;
}
}
else
{
base.DialogResult = DialogResult.Cancel;
foreach(PropertyPage page in _allPages)
page.onCancel();
FakeClose();
}
}
/// <summary>
/// The user clicked apply. Validate the current page's
/// data, and then send an apply message to every page
/// </summary>
/// <param name="o"></param>
/// <param name="e"></param>
void OnApplyClick(Object o, EventArgs e)
{
PropertyPage psp = _allPages[_tc.SelectedIndex];
if (psp.ValidateData())
{
SendApplyToAll();
DeactivateApplyButton();
}
}
#endregion
/// <summary>
/// Turn on the apply button
/// </summary>
public void ActivateApplyButton()
{
if (_btnApply != null)
_btnApply.Enabled = true;
}
/// <summary>
/// Turn off the apply button
/// </summary>
public void DeactivateApplyButton()
{
if(_btnApply != null)
_btnApply.Enabled = false;
}
/// <summary>
/// This sends the apply message to every
/// </summary>
private void SendApplyToAll()
{
foreach(PropertyPage page in _allPages)
{
page.Applied = true;
page.onApply();
}
}
//Added by Alexander Kachalkov
private void InitializeComponent()
{
//
// PropertySheet
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = SnapinBase.Translate("Properties");
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
//this.TopMost = true;
}
/// <summary>
/// We need to close this page (make it invisible), but
/// we don't want it to dispose itself. Instead, we'll
/// just muck with the form so the next time it's made visible,
/// it looks brand new
/// </summary>
private void FakeClose()
{
_fClosed = true;
Close();
}
//Added by Alexander Ovchinnikov for Close PropertySheet
public virtual void ClosePropertySheet( string key, object val )
{
base.DialogResult = DialogResult.Cancel;
foreach(PropertyPage page in _allPages)
page.onCancel();
FakeClose();
}
}
#endregion
#region Validate
/// <summary>
/// Validate Event Args
/// </summary>
public class ValidateEventArgs : System.EventArgs
{
protected bool valid = true;
public bool Valid
{
get { return valid; }
set { valid = value; }
}
}
/// <summary>
/// Validation Delegate
/// </summary>
public delegate bool CheckValidation();
#endregion
#region PropertySheetTabControl
/// <summary>
/// Custom TabControl to simulate a property sheet tabs
/// </summary>
public class PropertySheetTabControl : TabControl
{
private CheckValidation onSelectedIndexChanging;
public event CheckValidation SelectedIndexChanging
{
add
{
onSelectedIndexChanging += value;
}
remove
{
onSelectedIndexChanging -= value;
}
}
protected override void WndProc(ref Message m)
{
try
{
// See if this is a special Winforms notify message
if (m.Msg == ((int)WM.NOTIFY + 0x0400 + 0x1C00)) // WM_USER + WM_REFLECT
{
// lParam really is a pointer to a NMHDR structure....
NMHDR nm = new NMHDR();
nm = (NMHDR)Marshal.PtrToStructure(m.LParam, nm.GetType());
// See if this is our command
if (nm.code == unchecked((0U-550U)-2)) // TCN_SELCHANGING = TCN_FIRST - 2
{
if (onSelectedIndexChanging != null)
if (!onSelectedIndexChanging())
{
m.Result = (IntPtr)1;
return;
}
}
}
base.WndProc(ref m);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine("Error in winProc: " + e.Message);
}
}
}
#endregion
#region PropertyPageList
/// <summary>
/// Typed collection of PropertyPage objects to help out PropertySheet
/// </summary>
public class PropertyPageList : ArrayList
{
public new PropertyPage this[int index]
{
get
{
return (PropertyPage)(base[index]);
}
}
// Added by Alex Ovchinnikov for Dispose method in Propertysheet
public override void Clear( )
{
for( int iIndex = 0; iIndex < base.Count; iIndex++ )
{
base[ iIndex ] = null;
}
base.Clear( );
}
}
#endregion
}
|