jEnvEditor : edits the system and user variables

Download jenveditor.zip

Synopsis:

BlankListView.cs
ComponentEnabler.cs
ItemEditorDialog.cs
ListBase.cs
ListViewBase.cs
MainListView.cs
MainWindow.cs
NewItemDialog.cs
NewValueDialog.cs
OneColumnList.cs
RegistryWrapper.cs
RegListView.cs
SubListView.cs
SystemList.cs
TwoColumnList.cs
UndoList.cs
UndoListView.cs
UndoMemento.cs
UnitTests.cs
UserList.cs
winnotifier.cs


BlankListView.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
	/// <summary>
	/// Initial screen for list. Nothing is shown.
	/// </summary>
	class BlankListView : ListViewBase
	{
    public BlankListView(ListView parent, ComponentEnabler btns, UndoList undo) 
      : base(parent, undo)
    {
      btns.SetBlankList();
    }
    public override void ResetColumns()
    {
      //no columns to reset
    }
	}
}

ComponentEnabler.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
	/// <summary>
	/// Knows how to enable/disable buttons and menu items.
	/// </summary>
	public class ComponentEnabler
	{
    private Button mUndoBtn;
    private Button mDeleteBtn;
    private Button mUpBtn;
    private Button mDownBtn;
    private Button mEditBtn;
    private Button mNew;
    private Button mBackBtn;
    private MenuItem mSystemMenu;
    private MenuItem mUserMenu;
    
    public ComponentEnabler(Button undo, Button del, Button up, Button down, Button edit, 
      Button nw, Button back, MenuItem system, MenuItem user)
		{
      mUndoBtn = undo;
      mDeleteBtn = del;
      mUpBtn = up;
      mDownBtn = down;
      mEditBtn = edit;
      mNew = nw;
      mBackBtn = back;
      mSystemMenu = system;
      mUserMenu = user;
		}
    public void SetBlankList()
    {
      mUndoBtn.Enabled = false;
      mBackBtn.Enabled = false;
      mDeleteBtn.Enabled = false;
      mUpBtn.Enabled = false;
      mDownBtn.Enabled = false;
      mEditBtn.Enabled = false;
      mNew.Enabled = false;
      mSystemMenu.Enabled = true;
      mUserMenu.Enabled = true;
    }
    public void SetMainList()
    {
      mUndoBtn.Enabled = true;
      mBackBtn.Enabled = false;
      mDeleteBtn.Enabled = true;
      mUpBtn.Enabled = false;
      mDownBtn.Enabled = false;
      mEditBtn.Enabled = true;
      mNew.Enabled = true;
      mSystemMenu.Enabled = true;
      mUserMenu.Enabled = true;
    }
    public void SetSubList()
    {
      mUndoBtn.Enabled = false;
      mBackBtn.Enabled = true;
      mDeleteBtn.Enabled = true;
      mUpBtn.Enabled = true;
      mDownBtn.Enabled = true;
      mEditBtn.Enabled = true;
      mNew.Enabled = true;
      mSystemMenu.Enabled = false;
      mUserMenu.Enabled = false;
    }
  }
}

ItemEditorDialog.cs

Synopsis
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// Edits a single Text entry (for a OneColumn list)
  /// </summary>
  public class ItemEditorDialog : System.Windows.Forms.Form
  {
    System.Windows.Forms.Button mOK;
    System.Windows.Forms.Button mCancel;
    string mEditText;
    int mStartingHeight;
    private System.Windows.Forms.TextBox mTextBox;

    private System.ComponentModel.Container components = null;
    
    public ItemEditorDialog(string text)
    {
      mEditText = text;
      InitializeComponent();
      mTextBox.Text = mEditText;
      mStartingHeight = this.Height;
      this.mOK.DialogResult = DialogResult.OK;
      this.mCancel.DialogResult = DialogResult.Cancel;
    }
    public string EditText
    {
      get {return mEditText;}
    }
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if(components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

		#region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.mOK = new System.Windows.Forms.Button();
      this.mCancel = new System.Windows.Forms.Button();
      this.mTextBox = new System.Windows.Forms.TextBox();
      this.SuspendLayout();
      // 
      // mOK
      // 
      this.mOK.Location = new System.Drawing.Point(128, 72);
      this.mOK.Name = "mOK";
      this.mOK.TabIndex = 6;
      this.mOK.Text = "OK";
      // 
      // mCancel
      // 
      this.mCancel.Location = new System.Drawing.Point(264, 72);
      this.mCancel.Name = "mCancel";
      this.mCancel.Size = new System.Drawing.Size(80, 24);
      this.mCancel.TabIndex = 7;
      this.mCancel.Text = "Cancel";
      // 
      // mTextBox
      // 
      this.mTextBox.Location = new System.Drawing.Point(8, 40);
      this.mTextBox.Name = "mTextBox";
      this.mTextBox.Size = new System.Drawing.Size(488, 20);
      this.mTextBox.TabIndex = 8;
      this.mTextBox.Text = "textBox1";
      // 
      // ItemEditorDialog
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(506, 109);
      this.ControlBox = false;
      this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                  this.mTextBox,
                                                                  this.mCancel,
                                                                  this.mOK});
      this.MaximizeBox = false;
      this.MinimizeBox = false;
      this.Name = "ItemEditorDialog";
      this.ShowInTaskbar = false;
      this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
      this.Text = "ItemEditor";
      this.SizeChanged += new System.EventHandler(this.ItemEditor_HandleResize);
      this.Layout += new System.Windows.Forms.LayoutEventHandler(this.ItemEditor_HandleLayout);
      this.Closed += new System.EventHandler(this.ItemEditor_Closed);
      this.ResumeLayout(false);

    }
		#endregion

    private void ItemEditor_HandleResize(object sender, System.EventArgs e)
    {
      //keep the height the same, the width can change.
      this.Height = mStartingHeight;
    }
    private void ItemEditor_HandleLayout(object sender, LayoutEventArgs e)
    {
      this.Height = mStartingHeight;
      int hGap = 3;
      int vGap = 5;
      mTextBox.SetBounds(hGap,vGap,this.ClientSize.Width - (2*hGap), 0, BoundsSpecified.X | BoundsSpecified.Y | BoundsSpecified.Width);
      Invalidate();
    }
    private void ItemEditor_Closed(object sender, System.EventArgs e)
    {
      if (this.DialogResult != DialogResult.OK) return;
      mEditText = mTextBox.Text;
    }
  }
}

ListBase.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// Common code across lists
  /// </summary>
	abstract class ListBase
	{
    protected ListView mParent;
    
    public ListBase(ListView parent)
    {
      mParent = parent;
    }

    public abstract void ResetColumns();
    public abstract string GetValue(int selrow);
    public abstract void SetValue(int selrow, string val);
    
    public virtual void Remove(int selrow)
    {
      mParent.Items.RemoveAt(selrow);
      SetSelected(selrow);
    }
    public virtual bool EditItem(int selrow)
    {
      bool rc = false;
      ItemEditorDialog dlg = new ItemEditorDialog(GetValue(selrow));
      if (dlg.ShowDialog(mParent) == DialogResult.OK)
      {
        SetValue(selrow, dlg.EditText);
        rc = true;
      }
      dlg.Dispose();
      return rc;
    }
    protected void Clear()
    {
      mParent.Clear();
      ResetColumns();
    }
    protected bool IsDefined(string s)
    {
      foreach (ListViewItem item in mParent.Items)
        if (item.Text.ToLower().Equals(s.ToLower()))
          return true;
      return false;
    }
    protected void SetSelected(int selrow)
    {
      if (mParent.Items.Count == 0) return;
      if (selrow >= mParent.Items.Count)
        selrow = mParent.Items.Count - 1;
      mParent.Items[selrow].Selected = true;
      mParent.Focus();
    }
  }
}

ListViewBase.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
	/// <summary>
	/// base class for the different list views
	/// </summary>
	abstract class ListViewBase
	{
    protected ListView mParent;
    protected UndoList mUndoList;

    public ListViewBase(ListView parent, UndoList undo)
    {
      mParent = parent;
      mUndoList = undo;
    }
    public virtual void SetLayout(int x, int y, int width, int height)
    {
      SetBounds(x, y, width, height);
      ResetColumns();
    }
    public abstract void ResetColumns();
    public virtual void Undo() {}
    public virtual void MoveSelectedDown() {}
    public virtual void MoveSelectedUp() {}
    public virtual void DeleteSelected() {}
    public virtual int Edit() {return -1; }
    public virtual void Back() {}
    public virtual void LoadSystemSet() {}
    public virtual void LoadUserSet() {}
    public virtual void AddNew() {}
    public virtual void Save() {}
    public virtual void Restore(string newvalue) {}
    public virtual string GetSubListValue() {return null;}
    public virtual string GetValue(int selrow) {return null;}

    protected void SetBounds(int x, int y, int width, int height)
    {
      mParent.SetBounds(x, y, width, height);
    }
    protected int SelectedIndex()
    {
      if (mParent.SelectedIndices.Count == 0) return -1;
      return mParent.SelectedIndices[0];
    }
	}
}

MainListView.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// The list view to show a two column list.
  /// </summary>
  class MainListView : ListViewBase
  {
    private TwoColumnList mList;
    private ComponentEnabler mButtons;

    private int mCurrentSublistSelectedIndex;
    private string mCurrentSublistSelectedValue;

    public MainListView(ListView parent, ComponentEnabler btns, UndoList undo) 
      : base(parent, undo)
    {
      mButtons = btns;
      mButtons.SetMainList();
    }
    public override void ResetColumns()
    {
      mList.ResetColumns();
    }
    public override void Undo()
    {
      UndoMemento mem = mUndoList.Pop();
      if (mem == null) return;

      if (mem.ListName.Equals("system") && !mList.ListName().Equals("system"))
        LoadSystemSet();
      else if (mem.ListName.Equals("user") && !mList.ListName().Equals("user"))
        LoadUserSet();
      
      mList.Undo(mem);
    }
    public override int Edit()          
    {
      int selrow = SelectedIndex();
      if (selrow == -1) return -1;
      if (mList.HasSubList(selrow))
      {
        mCurrentSublistSelectedIndex = selrow;
        mCurrentSublistSelectedValue = mList.GetValue(selrow);
        return selrow;
      }
      mList.EditItem(selrow);
      return -1;
    }
    public override void LoadSystemSet()
    {
      mList = new SystemList(mParent, mUndoList);
    }
    public override void LoadUserSet()
    {
      mList = new UserList(mParent, mUndoList);
    }
    public override void AddNew()
    {
      mList.AddNew();
    }
    public override void DeleteSelected()
    {
      int selrow = SelectedIndex();
      if (selrow == -1) return;
      mList.Remove(selrow);
    }
    public override string GetValue(int selrow) 
    {
      return mList.GetValue(selrow);
    }
    public override void Restore(string newvalue)
    {
      mList.Load();
      mButtons.SetMainList();
      if (newvalue.Equals(mCurrentSublistSelectedValue)) return;
      mList.SetValue(mCurrentSublistSelectedIndex, mCurrentSublistSelectedValue, newvalue);
    }
  }
}

MainWindow.cs

Synopsis
using System;
using System.Windows.Forms;
using System.ComponentModel;

namespace jEnvEditor
{
  /// <summary>
  /// main window.
  /// </summary>
  public class MainWindow : System.Windows.Forms.Form
  {
    private ComponentEnabler mButtons;
    private RegListView mList;
    private System.ComponentModel.Container components = null;
    private System.Windows.Forms.MainMenu mainMenu1;
    private System.Windows.Forms.MenuItem menuItem3;
    private System.Windows.Forms.MenuItem mSystemMenu;
    private System.Windows.Forms.MenuItem mUserMenu;
    private System.Windows.Forms.Button mDeleteBtn;
    private System.Windows.Forms.Button mUpBtn;
    private System.Windows.Forms.Button mDownBtn;
    private System.Windows.Forms.Button mEditBtn;
    private System.Windows.Forms.Button mNew;
    private System.Windows.Forms.Button mBackBtn;
    private System.Windows.Forms.Button mUndoBtn;
    private System.Windows.Forms.MenuItem menuItem2;
    private System.Windows.Forms.MenuItem mUndoMenu;

    public MainWindow()
    {
      InitializeComponent();
      mButtons = new ComponentEnabler(mUndoBtn, mDeleteBtn, 
        mUpBtn, mDownBtn, mEditBtn, mNew, mBackBtn,
        mSystemMenu, mUserMenu);
      mList = new RegListView(mButtons);
      mList.InitializeComponent();
      this.Controls.Add(mList);
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      Win32SDK.SendNotification();
    
      if( disposing )
      {
        if (components != null) 
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

		#region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.mainMenu1 = new System.Windows.Forms.MainMenu();
      this.menuItem3 = new System.Windows.Forms.MenuItem();
      this.mSystemMenu = new System.Windows.Forms.MenuItem();
      this.mUserMenu = new System.Windows.Forms.MenuItem();
      this.menuItem2 = new System.Windows.Forms.MenuItem();
      this.mUndoMenu = new System.Windows.Forms.MenuItem();
      this.mDeleteBtn = new System.Windows.Forms.Button();
      this.mUpBtn = new System.Windows.Forms.Button();
      this.mDownBtn = new System.Windows.Forms.Button();
      this.mEditBtn = new System.Windows.Forms.Button();
      this.mNew = new System.Windows.Forms.Button();
      this.mBackBtn = new System.Windows.Forms.Button();
      this.mUndoBtn = new System.Windows.Forms.Button();
      this.SuspendLayout();
      // 
      // mainMenu1
      // 
      this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                              this.menuItem3});
      // 
      // menuItem3
      // 
      this.menuItem3.Index = 0;
      this.menuItem3.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
                                                                              this.mSystemMenu,
                                                                              this.mUserMenu,
                                                                              this.menuItem2,
                                                                              this.mUndoMenu});
      this.menuItem3.Text = "View";
      // 
      // mSystemMenu
      // 
      this.mSystemMenu.Index = 0;
      this.mSystemMenu.Text = "System";
      this.mSystemMenu.Click += new System.EventHandler(this.mSystemMenu_Click);
      // 
      // mUserMenu
      // 
      this.mUserMenu.Index = 1;
      this.mUserMenu.Text = "User";
      this.mUserMenu.Click += new System.EventHandler(this.mUserMenu_Click);
      // 
      // menuItem2
      // 
      this.menuItem2.Index = 2;
      this.menuItem2.Text = "-";
      // 
      // mUndoMenu
      // 
      this.mUndoMenu.Index = 3;
      this.mUndoMenu.Text = "Undo List";
      this.mUndoMenu.Click += new System.EventHandler(this.mUndoMenu_Click);
      // 
      // mDeleteBtn
      // 
      this.mDeleteBtn.Location = new System.Drawing.Point(0, 8);
      this.mDeleteBtn.Name = "mDeleteBtn";
      this.mDeleteBtn.Size = new System.Drawing.Size(72, 24);
      this.mDeleteBtn.TabIndex = 1;
      this.mDeleteBtn.Text = "Delete";
      this.mDeleteBtn.Click += new System.EventHandler(this.mDeleteBtn_Click);
      // 
      // mUpBtn
      // 
      this.mUpBtn.Location = new System.Drawing.Point(0, 216);
      this.mUpBtn.Name = "mUpBtn";
      this.mUpBtn.Size = new System.Drawing.Size(72, 24);
      this.mUpBtn.TabIndex = 2;
      this.mUpBtn.Text = "Up";
      this.mUpBtn.Click += new System.EventHandler(this.mUpBtn_Click);
      // 
      // mDownBtn
      // 
      this.mDownBtn.Location = new System.Drawing.Point(0, 240);
      this.mDownBtn.Name = "mDownBtn";
      this.mDownBtn.Size = new System.Drawing.Size(72, 24);
      this.mDownBtn.TabIndex = 3;
      this.mDownBtn.Text = "Down";
      this.mDownBtn.Click += new System.EventHandler(this.mDownBtn_Click);
      // 
      // mEditBtn
      // 
      this.mEditBtn.Location = new System.Drawing.Point(0, 32);
      this.mEditBtn.Name = "mEditBtn";
      this.mEditBtn.Size = new System.Drawing.Size(72, 24);
      this.mEditBtn.TabIndex = 4;
      this.mEditBtn.Text = "Edit";
      this.mEditBtn.Click += new System.EventHandler(this.mEditBtn_Click);
      // 
      // mNew
      // 
      this.mNew.Location = new System.Drawing.Point(0, 56);
      this.mNew.Name = "mNew";
      this.mNew.Size = new System.Drawing.Size(72, 24);
      this.mNew.TabIndex = 5;
      this.mNew.Text = "New";
      this.mNew.Click += new System.EventHandler(this.mNew_Click);
      // 
      // mBackBtn
      // 
      this.mBackBtn.Location = new System.Drawing.Point(0, 192);
      this.mBackBtn.Name = "mBackBtn";
      this.mBackBtn.Size = new System.Drawing.Size(72, 24);
      this.mBackBtn.TabIndex = 6;
      this.mBackBtn.Text = "< Back";
      this.mBackBtn.Click += new System.EventHandler(this.mBackBtn_Click);
      // 
      // mUndoBtn
      // 
      this.mUndoBtn.Location = new System.Drawing.Point(0, 96);
      this.mUndoBtn.Name = "mUndoBtn";
      this.mUndoBtn.TabIndex = 7;
      this.mUndoBtn.Text = "Undo";
      this.mUndoBtn.Click += new System.EventHandler(this.mUndo_Click);
      // 
      // MainWindow
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(600, 437);
      this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                  this.mUndoBtn,
                                                                  this.mBackBtn,
                                                                  this.mNew,
                                                                  this.mEditBtn,
                                                                  this.mDownBtn,
                                                                  this.mUpBtn,
                                                                  this.mDeleteBtn});
      this.Menu = this.mainMenu1;
      this.Name = "MainWindow";
      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
      this.Text = "jEnvEditor - Environment Variables Editor";
      this.Layout += new System.Windows.Forms.LayoutEventHandler(this.MainWindow_HandleLayout);
      this.ResumeLayout(false);

    }
		#endregion

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main() 
    {
      Application.Run(new MainWindow());
    }
    private void MainWindow_HandleLayout(object sender, LayoutEventArgs e)
    {
      int hGap = 3;
      mDeleteBtn.SetBounds(0,0,0,0, BoundsSpecified.X);
      mEditBtn.SetBounds(0,0,0,0, BoundsSpecified.X);
      mUpBtn.SetBounds(0,0,0,0, BoundsSpecified.X);
      mDownBtn.SetBounds(0,0,0,0, BoundsSpecified.X);

      mList.SetLayout(mDeleteBtn.Width + hGap,0,this.ClientSize.Width,this.ClientSize.Height);
    }
    private void mSystemMenu_Click(object sender, System.EventArgs e)
    {
      mList.LoadSystemSet();
    }
    private void mUserMenu_Click(object sender, System.EventArgs e)
    {
      mList.LoadUserSet();
    }
    private void mNew_Click(object sender, System.EventArgs e)
    {
      mList.AddNew();
    }
    private void mBackBtn_Click(object sender, System.EventArgs e)
    {
      mList.Back();
    }
    private void mUpBtn_Click(object sender, System.EventArgs e)
    {
      mList.MoveSelectedUp();
    }
    private void mDownBtn_Click(object sender, System.EventArgs e)
    {
      mList.MoveSelectedDown();
    }
    private void mDeleteBtn_Click(object sender, System.EventArgs e)
    {
      mList.DeleteSelected();
    }
    private void mEditBtn_Click(object sender, System.EventArgs e)
    {
      mList.Edit(sender, e);
    }
    private void mUndo_Click(object sender, System.EventArgs e)
    {
      mList.Undo();
    }
    private void mUndoMenu_Click(object sender, System.EventArgs e)
    {
      mList.ShowUndoList();    
    }
  }
}

NewItemDialog.cs

Synopsis
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// Gets the Name & Value for a new list item
  /// </summary>
  public class NewItemDialog : System.Windows.Forms.Form
  {
    System.Windows.Forms.Button mOK;
    System.Windows.Forms.Button mCancel;
    string mValue;
    string mName;
    int mStartingHeight;
    private System.Windows.Forms.TextBox mValueTextBox;
    private System.Windows.Forms.TextBox mNameTextBox;
    private System.Windows.Forms.StatusBar mStatusBar;

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;
    
    public NewItemDialog(string name, string val)
    {
      mValue = val;
      mName = name;
      InitializeComponent();

      mNameTextBox.Text = mName;
      mValueTextBox.Text = mValue;
      mStartingHeight = this.Height;
      StatusBarPanel panel1 = new StatusBarPanel();
      panel1.BorderStyle = StatusBarPanelBorderStyle.Sunken;
      panel1.Text = "Enter a new Name and Value...";
      panel1.AutoSize = StatusBarPanelAutoSize.Spring;
      mStatusBar.Panels.Add(panel1);

      this.mOK.DialogResult = DialogResult.OK;
      this.mCancel.DialogResult = DialogResult.Cancel;
    }
    public string ValueText
    {
      get {return mValue;}
    }
    public string NameText
    {
      get {return mName;}
    }
    public string StatusText
    {
      set {mStatusBar.Panels[0].Text = value;}
    }
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if(components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

		#region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.mOK = new System.Windows.Forms.Button();
      this.mCancel = new System.Windows.Forms.Button();
      this.mValueTextBox = new System.Windows.Forms.TextBox();
      this.mNameTextBox = new System.Windows.Forms.TextBox();
      this.mStatusBar = new System.Windows.Forms.StatusBar();
      this.SuspendLayout();
      // 
      // mOK
      // 
      this.mOK.Location = new System.Drawing.Point(128, 72);
      this.mOK.Name = "mOK";
      this.mOK.TabIndex = 2;
      this.mOK.Text = "OK";
      // 
      // mCancel
      // 
      this.mCancel.Location = new System.Drawing.Point(264, 72);
      this.mCancel.Name = "mCancel";
      this.mCancel.Size = new System.Drawing.Size(80, 24);
      this.mCancel.TabIndex = 3;
      this.mCancel.Text = "Cancel";
      // 
      // mValueTextBox
      // 
      this.mValueTextBox.Location = new System.Drawing.Point(8, 40);
      this.mValueTextBox.Name = "mValueTextBox";
      this.mValueTextBox.Size = new System.Drawing.Size(488, 20);
      this.mValueTextBox.TabIndex = 1;
      this.mValueTextBox.Text = "Value";
      // 
      // mNameTextBox
      // 
      this.mNameTextBox.Location = new System.Drawing.Point(8, 16);
      this.mNameTextBox.Name = "mNameTextBox";
      this.mNameTextBox.Size = new System.Drawing.Size(488, 20);
      this.mNameTextBox.TabIndex = 0;
      this.mNameTextBox.Text = "Name";
      // 
      // mStatusBar
      // 
      this.mStatusBar.Location = new System.Drawing.Point(0, 119);
      this.mStatusBar.Name = "mStatusBar";
      this.mStatusBar.ShowPanels = true;
      this.mStatusBar.Size = new System.Drawing.Size(506, 22);
      this.mStatusBar.TabIndex = 4;
      this.mStatusBar.Text = "Enter a new name and value";
      // 
      // NewItemDialog
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(506, 141);
      this.ControlBox = false;
      this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                  this.mStatusBar,
                                                                  this.mNameTextBox,
                                                                  this.mValueTextBox,
                                                                  this.mCancel,
                                                                  this.mOK});
      this.MaximizeBox = false;
      this.MinimizeBox = false;
      this.Name = "NewItemDialog";
      this.ShowInTaskbar = false;
      this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
      this.Text = "ItemEditor";
      this.SizeChanged += new System.EventHandler(this.ItemEditor_HandleResize);
      this.Layout += new System.Windows.Forms.LayoutEventHandler(this.ItemEditor_HandleLayout);
      this.Closed += new System.EventHandler(this.ItemEditor_Closed);
      this.ResumeLayout(false);

    }
		#endregion
    private void ItemEditor_HandleResize(object sender, System.EventArgs e)
    {
      //keep the height the same, the width can change
      this.Height = mStartingHeight;
    }
    private void ItemEditor_HandleLayout(object sender, LayoutEventArgs e)
    {
      this.Height = mStartingHeight;
      int hGap = 3;
      int vGap = 5;
      mNameTextBox.SetBounds(hGap,vGap,this.ClientSize.Width - (2*hGap), 0, BoundsSpecified.X | BoundsSpecified.Y | BoundsSpecified.Width);
      mValueTextBox.SetBounds(hGap,mNameTextBox.Height + vGap,this.ClientSize.Width - (2*hGap), 0, BoundsSpecified.X | BoundsSpecified.Y | BoundsSpecified.Width);
      Invalidate();
    }
    private void ItemEditor_Closed(object sender, System.EventArgs e)
    {
      if (this.DialogResult != DialogResult.OK) return;
      mName = mNameTextBox.Text;
      mValue = mValueTextBox.Text;
    }
  }
}

NewValueDialog.cs

Synopsis
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// create a new list item for a one column list
  /// </summary>
  public class NewValueDialog : System.Windows.Forms.Form
  {
    System.Windows.Forms.Button mOK;
    System.Windows.Forms.Button mCancel;
    string mValue;
    int mStartingHeight;
    private System.Windows.Forms.TextBox mValueTextBox;
    private System.Windows.Forms.StatusBar mStatusBar;

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;
    
    public NewValueDialog(string val)
    {
      mValue = val;
      InitializeComponent();
      mValueTextBox.Text = mValue;
      mStartingHeight = this.Height;
      StatusBarPanel panel1 = new StatusBarPanel();
      panel1.BorderStyle = StatusBarPanelBorderStyle.Sunken;
      panel1.Text = "Enter a new Value...";
      panel1.AutoSize = StatusBarPanelAutoSize.Spring;
      mStatusBar.Panels.Add(panel1);

      this.mOK.DialogResult = DialogResult.OK;
      this.mCancel.DialogResult = DialogResult.Cancel;
    }
    public string ValueText
    {
      get {return mValue;}
    }
    public string StatusText
    {
      set {mStatusBar.Panels[0].Text = value;}
    }
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
      if( disposing )
      {
        if(components != null)
        {
          components.Dispose();
        }
      }
      base.Dispose( disposing );
    }

		#region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.mOK = new System.Windows.Forms.Button();
      this.mCancel = new System.Windows.Forms.Button();
      this.mValueTextBox = new System.Windows.Forms.TextBox();
      this.mStatusBar = new System.Windows.Forms.StatusBar();
      this.SuspendLayout();
      // 
      // mOK
      // 
      this.mOK.Location = new System.Drawing.Point(128, 72);
      this.mOK.Name = "mOK";
      this.mOK.TabIndex = 2;
      this.mOK.Text = "OK";
      // 
      // mCancel
      // 
      this.mCancel.Location = new System.Drawing.Point(264, 72);
      this.mCancel.Name = "mCancel";
      this.mCancel.Size = new System.Drawing.Size(80, 24);
      this.mCancel.TabIndex = 3;
      this.mCancel.Text = "Cancel";
      // 
      // mValueTextBox
      // 
      this.mValueTextBox.Location = new System.Drawing.Point(8, 40);
      this.mValueTextBox.Name = "mValueTextBox";
      this.mValueTextBox.Size = new System.Drawing.Size(488, 20);
      this.mValueTextBox.TabIndex = 1;
      this.mValueTextBox.Text = "Value";
      // 
      // mStatusBar
      // 
      this.mStatusBar.Location = new System.Drawing.Point(0, 119);
      this.mStatusBar.Name = "mStatusBar";
      this.mStatusBar.ShowPanels = true;
      this.mStatusBar.Size = new System.Drawing.Size(506, 22);
      this.mStatusBar.TabIndex = 4;
      this.mStatusBar.Text = "Enter a new  value";
      // 
      // NewValueDialog
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(506, 141);
      this.ControlBox = false;
      this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                  this.mStatusBar,
                                                                  this.mValueTextBox,
                                                                  this.mCancel,
                                                                  this.mOK});
      this.MaximizeBox = false;
      this.MinimizeBox = false;
      this.Name = "NewValueDialog";
      this.ShowInTaskbar = false;
      this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
      this.Text = "ItemEditor";
      this.SizeChanged += new System.EventHandler(this.ItemEditor_HandleResize);
      this.Layout += new System.Windows.Forms.LayoutEventHandler(this.ItemEditor_HandleLayout);
      this.Closed += new System.EventHandler(this.ItemEditor_Closed);
      this.ResumeLayout(false);

    }
		#endregion
    private void ItemEditor_HandleResize(object sender, System.EventArgs e)
    {
      this.Height = mStartingHeight;
    }
    private void ItemEditor_HandleLayout(object sender, LayoutEventArgs e)
    {
      this.Height = mStartingHeight;
      int hGap = 3;
      int vGap = 5;
      mValueTextBox.SetBounds(hGap,vGap,this.ClientSize.Width - (2*hGap), 0, BoundsSpecified.X | BoundsSpecified.Y | BoundsSpecified.Width);
      Invalidate();
    }
    private void ItemEditor_Closed(object sender, System.EventArgs e)
    {
      if (this.DialogResult != DialogResult.OK) return;
      mValue = mValueTextBox.Text;
    }
  }
}

OneColumnList.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// A one column list. One column lists are used for semicolon delimited
  /// entries (like PATH)
  /// </summary>
  class OneColumnList : ListBase
  {
    public OneColumnList(ListView parent)
      : base(parent)
    {
    }
    public void Swap(int row1, int row2)
    {
      if (row1 >= row2) return;
      ListViewItem nextitem = mParent.Items[row2];
      ListViewItem item = mParent.Items[row1];
      mParent.Items.RemoveAt(row2);
      mParent.Items.RemoveAt(row1);
      mParent.Items.Insert(row1, nextitem);
      mParent.Items.Insert(row2, item);
    }
    public void Load(string s)
    {
      Clear();
      int lastposn = 0;
      int row = 0;
      for(;;)
      {
        int posn = s.IndexOf(';', lastposn);
        if (posn == -1)
        {
          InsertRow(row, s.Substring(lastposn));
          break;
        }

        InsertRow(row, s.Substring(lastposn, posn - lastposn));
        lastposn = posn + 1;
        ++row;
      }
      SetSelected(0);
    }
    public override void ResetColumns()
    {
      mParent.Columns.Clear();
      mParent.Columns.Add("Value", mParent.ClientSize.Width, HorizontalAlignment.Left);
    }
    public void AddNew()
    {
      string val = "<value>";
      NewValueDialog dlg = new NewValueDialog(val);
      while(dlg.ShowDialog(mParent) == DialogResult.OK)
      {
        if (dlg.ValueText.Equals("<value>")) 
        {
          dlg.StatusText = "Please enter a new Value...";
          continue;
        }
        if (IsDefined(dlg.ValueText))
        {
          dlg.StatusText = "That value is already in use...";
          continue;
        }
        AddNewRow(dlg.ValueText);
        break;
      }
      dlg.Dispose();
    }
    public override string GetValue(int selrow)
    {
      return mParent.Items[selrow].Text;
    }
    public override void SetValue(int selrow, string val)
    {
      mParent.Items[selrow].Text = val;
    }
    public string GetValuesAsString()
    {
      bool addsemicolon = false;
      string val = "";
      foreach(ListViewItem item in mParent.Items)
      {
        if (addsemicolon)
          val += ";";
        val += item.Text;
        addsemicolon = true;
      }
      return val;
    }
    //----------- private from here on
    private void AddNewRow(string val)
    {
      ListViewItem item = mParent.Items.Add(val);
      item.Selected = true;
      mParent.Focus();
    }
    private void InsertRow(int row, string val)
    {
      mParent.Items.Insert(row, val);
    }
  }
}

RegistryWrapper.cs

Synopsis
using System;
using Microsoft.Win32;

namespace jEnvEditor
{
  /// <summary>
  /// Summary description for RegistryWrapper.
  /// </summary>
  public class RegistryWrapper
  {
    RegistryKey mKey;
    RegistryKey mRootKey;
    string mSubKeyName;
    public static RegistryWrapper SystemEnvVariablesKey()
    {
      return new RegistryWrapper(Registry.LocalMachine, @"SYSTEM\CurrentControlSet\Control\Session Manager\Environment");
    }
    public static RegistryWrapper UserEnvVariablesKey()
    {
      return new RegistryWrapper(Registry.CurrentUser, "Environment");
    }
    private RegistryWrapper(RegistryKey rootkey, string subkey)
    {
      mRootKey = rootkey;
      mSubKeyName = subkey;
      mKey = mRootKey.OpenSubKey(mSubKeyName, true);
    }
    public string[] Names()
    {
      return mKey.GetValueNames();
    }
    public string ValueOf(string name)
    {
      return mKey.GetValue(name).ToString();
    }

    //these change values!
    public void AddNewRow(string name, string val)
    {
      mKey.SetValue(name, val);
      mKey.Flush();
    }
    public void Remove(string name)
    {
      mKey.DeleteValue(name);
      mKey.Flush();
    }
    public void SetValue(string name, string val)
    {
      mKey.SetValue(name, val);
      mKey.Flush();
    }
  }
}

RegListView.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// Handles switching between different views and pass-thrus otherwise.
  /// </summary>
  public class RegListView : ListView
  {
    private static readonly string cUndoFilename = "undolist.txt";
    private UndoList mUndoList = new UndoList(cUndoFilename);
    private ComponentEnabler mButtons;

    private ListViewBase mView;
    private ListViewBase mSavedView = null;

    public RegListView(ComponentEnabler btns) : base()
    {
      mButtons = btns;
      mUndoList.Load();
      mView = new BlankListView(this, mButtons, mUndoList);
    }
    public void InitializeComponent()
    {
      this.FullRowSelect = true;
      this.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
      this.HideSelection = false;
      this.LabelWrap = false;
      this.Location = new System.Drawing.Point(80, 8);
      this.MultiSelect = false;
      this.Name = "mList";
      this.Size = new System.Drawing.Size(472, 328);
      this.TabIndex = 0;
      this.View = System.Windows.Forms.View.Details;
      this.DoubleClick += new System.EventHandler(Edit);
    }
    public void Undo()
    {
      mView.Undo();
    }
    public void ShowUndoList()
    {
      mUndoList.Show();    
    }
    public void MoveSelectedUp()
    {
      mView.MoveSelectedUp();
    }
    public void MoveSelectedDown()
    {
      mView.MoveSelectedDown();
    }
    public void DeleteSelected()
    {
      mView.DeleteSelected();
    }
    public void Edit(object sender, System.EventArgs e)
    {
      int selrow = mView.Edit();
      if (selrow != -1)
        LoadSublist(selrow);
    }
    public void Back()
    {
      string newvalue = mView.GetSubListValue();
      if (newvalue == null) return;
      Restore(newvalue);
    }
    public void LoadSystemSet()
    {
      mView = new MainListView(this, mButtons, mUndoList);
      mView.LoadSystemSet();
    }
    public void LoadUserSet()
    {
      mView = new MainListView(this, mButtons, mUndoList);
      mView.LoadUserSet();
    }
    public void SetLayout(int x, int y, int width, int height)
    {
      mView.SetLayout(x, y, width, height);
    }
    public void AddNew()
    {
      mView.AddNew();
    }

    //private from here on
    private void LoadSublist(int selrow)
    {
      mSavedView = mView;
      mView = new SubListView(mView.GetValue(selrow), this, mButtons, mUndoList);
    }  
    private void Restore(string newvalue)
    {
      mView = mSavedView;
      mView.Restore(newvalue);
    }
  }
}

SubListView.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
	/// <summary>
	/// A view of one column list.
	/// </summary>
	class SubListView : ListViewBase
	{
    OneColumnList mList;

    public SubListView(string sublist, ListView parent, ComponentEnabler btns, UndoList undo) 
       : base(parent, undo)
		{
      btns.SetSubList();
    
      mList = new OneColumnList(mParent);
      mList.Load(sublist);
		}
    public override void ResetColumns()
    {
      mList.ResetColumns();
    }
    public override void AddNew()
    {
      mList.AddNew();
    }
    public override void MoveSelectedUp()
    {
      int selrow = SelectedIndex();
      if (selrow == -1 || selrow == 0) return;
      mList.Swap(selrow-1, selrow);
    }
    public override void MoveSelectedDown()
    {
      int selrow = SelectedIndex();
      if (selrow == -1 || selrow == mParent.Items.Count - 1) return;
      mList.Swap(selrow, selrow+1);
    }
    public override void DeleteSelected()
    {
      int selrow = SelectedIndex();
      if (selrow == -1) return;
      mList.Remove(selrow);
    }
    public override string GetSubListValue() 
    {
      return mList.GetValuesAsString();
    }
    public override int Edit()          
    {
      int selrow = SelectedIndex();
      if (selrow == -1) return -1;
      mList.EditItem(selrow);
      return -1;
    }
  }
}

SystemList.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// The system environment variables
  /// </summary>
  class SystemList : TwoColumnList
  {
    public SystemList(ListView parent, UndoList ul)
      : base("system", parent, ul, RegistryWrapper.SystemEnvVariablesKey())
    {
    }
  }
}

TwoColumnList.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// Handles the functionality for a name/value list (the main list views)
  /// </summary>
  class TwoColumnList : ListBase
  {
    private UndoList mUndoList;
    private readonly string mListName;

    private int mCol0width = 100;
    private RegistryWrapper mReg;

    public TwoColumnList(string listname, ListView parent, UndoList ul, RegistryWrapper reg)
      : base(parent)
    {
      mListName = listname;
      mUndoList = ul;
      mReg = reg;
      Load();
    }
    private string GetName(int selrow)
    {
      return mParent.Items[selrow].Text;
    }
    public string ListName()
    {
      return mListName;
    }
    public override void Remove(int selrow)
    {
      mUndoList.Push(new UndoMemento(ListName(), "delete", GetName(selrow), GetValue(selrow)));
      RegRemove(GetName(selrow));
    }
    public void Load()
    {
      Clear();
      string[] values = mReg.Names();
      for(int row = 0; row < values.Length; ++row)
        InsertRow(row, values[row], mReg.ValueOf(values[row]));
      mParent.Sort();
      SetSelected(0);
    }
    public override void ResetColumns()
    {
      mParent.Columns.Clear();
      mParent.Columns.Add("Name", 0, HorizontalAlignment.Left);
      mParent.Columns.Add("Value", 0, HorizontalAlignment.Left);
      mParent.Columns[0].Width = mCol0width;
      mParent.Columns[1].Width = mParent.ClientSize.Width - mParent.Columns[0].Width;
    }
    public override bool EditItem(int selrow)
    {
      string oldvalue = GetValue(selrow);
      bool rc = base.EditItem(selrow);
      if (!rc) return rc;
      if (GetValue(selrow).Equals(oldvalue)) return rc;
      SetValue(selrow, oldvalue, GetValue(selrow));
      return rc;
    }
    public void AddNew()
    {
      string name = "<name>";
      string val = "<value>";
      NewItemDialog dlg = new NewItemDialog(name, val);
      while(dlg.ShowDialog(mParent) == DialogResult.OK)
      {
        if (dlg.NameText.Equals("<name>"))
        {
          dlg.StatusText = "Please enter a new Name...";
          continue;
        }
        if (dlg.ValueText.Equals("<value>")) 
        {
          dlg.StatusText = "Please enter a new Value...";
          continue;
        }
        if (IsDefined(dlg.NameText))
        {
          dlg.StatusText = "That name is already in use...";
          continue;
        }
        mUndoList.Push(new UndoMemento(this.ListName(), "add", dlg.NameText, dlg.ValueText));
        RegAddNewRow(dlg.NameText, dlg.ValueText);
        break;
      }
      dlg.Dispose();
    }
    public bool HasSubList(int selrow)
    {
      return GetValue(selrow).IndexOf(';') != -1;
    }
    public override string GetValue(int selrow)
    {
      return mParent.Items[selrow].SubItems[1].Text;
    }
    public override void SetValue(int selrow, string val)
    {
      mParent.Items[selrow].SubItems[1].Text = val;
    }
    public void SetValue(int row, string oldvalue, string newvalue)
    {
     mUndoList.Push(new UndoMemento(ListName(), "edit", GetName(row), oldvalue));
     RegSetValue(GetName(row), newvalue);
    }
    public void Undo(UndoMemento mem)
    {
      switch (mem.Action)
      {
        case "delete" : 
          RegAddNewRow(mem.Name, mem.Value);
          break;
        case "add" : 
          RegRemove(mem.Name);
          break;
        case "edit" : 
          RegSetValue(mem.Name, mem.Value);
          break;
      }
    }
    //----------- private from here on
    private int IndexOf(string name)
    {
      for(int row = 0; row < mParent.Items.Count; ++row)
      {
        if (mParent.Items[row].Text.Equals(name))
          return row;
      }
      return -1;
    }
    private void InsertRow(int row, string name, string val)
    {
      mParent.Items.Insert(row, name);
      mParent.Items[row].SubItems.Add(val);
    }

    //these routines change the registry!
    private void RegAddNewRow(string name, string val)
    {
      mReg.AddNewRow(name, val);
      ListViewItem item = mParent.Items.Add(name);
      item.SubItems.Add(val);
      item.Selected = true;
      mParent.Focus();
      mParent.Sort();
    }
    private void RegRemove(string name)
    {
      mReg.Remove(name);
      base.Remove(IndexOf(name));
    }
    private void RegSetValue(string name, string val)
    {
      mReg.SetValue(name, val);
      SetValue(IndexOf(name), val);
    }
  }
}

UndoList.cs

Synopsis
using System;
using System.IO;
using System.Collections;

namespace jEnvEditor
{
  /// <summary>
  /// handles undo of all user actions
  /// </summary>
  public class UndoList
  {
    private ArrayList mList = new ArrayList();
    private string mFilename;
    UndoListView mView = new UndoListView();

    public UndoList(string fname)
    {
      string dir = Win32SDK.StartupDirectory;
      mFilename = dir + '\\' + fname;
    }
    public void Load()
    {
      try 
      {
        StreamReader sr = new StreamReader(mFilename);
        while (sr.Peek() > -1)
          PushNoSave(UndoMemento.Parse(sr.ReadLine()));
        sr.Close();
      } 
      catch(Exception )
      {
      }
    }
    public void Save()
    {
      StreamWriter sw = new StreamWriter(mFilename);
      for(int i = mList.Count - 1; i >= 0; --i)
        ((UndoMemento)mList[i]).WriteOn(sw);
      sw.Flush();
      sw.Close();
    }
    public void Push(UndoMemento mem)
    {
      PushNoSave(mem);
      Save();
    }
    public UndoMemento Pop()
    {
      if (Count == 0) return null;
      UndoMemento mem = (UndoMemento) mList[0];
      mList.RemoveAt(0);
      mView.AddList(mList);
      Save();
      return mem;
    }
    public int Count
    {
      get { return mList.Count; }
    }
    public void Show()
    {
      mView.AddList(mList);
      mView.Show();
    }
    private void PushNoSave(UndoMemento mem)
    {
      mList.Insert(0, mem);
      mView.AddList(mList);
    }
  }
}

UndoListView.cs

Synopsis
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// Shows the current undo list
  /// </summary>
  public class UndoListView : System.Windows.Forms.Form
  {
    private System.Windows.Forms.ListView mList;
    /// <summary>
    /// Required designer variable.
    /// </summary>
    //private System.ComponentModel.Container components = null;

    public UndoListView()
    {
      InitializeComponent();

      mList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
      mList.View = System.Windows.Forms.View.Details;
    }
    public void AddList(ArrayList list)
    {
      mList.Items.Clear();
      for(int row = 0; row < list.Count; ++row)
      {
        string[] arr = ((UndoMemento)list[row]).ToArray();
        ListViewItem item = new ListViewItem();
        item.Text = arr[0];
        item.SubItems.Add(arr[1]);
        item.SubItems.Add(arr[2]);
        item.SubItems.Add(arr[3]);
        mList.Items.Add(item);
      }
    }

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    protected override void Dispose( bool disposing )
    {
//      if( disposing )
//      {
//        if(components != null)
//        {
//          components.Dispose();
//        }
//      }
    //  base.Dispose( disposing );
    }

		#region Windows Form Designer generated code
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
      this.mList = new System.Windows.Forms.ListView();
      this.SuspendLayout();
      // 
      // mList
      // 
      this.mList.CausesValidation = false;
      this.mList.Location = new System.Drawing.Point(32, 32);
      this.mList.MultiSelect = false;
      this.mList.Name = "mList";
      this.mList.Size = new System.Drawing.Size(456, 280);
      this.mList.TabIndex = 0;
      // 
      // UndoListView
      // 
      this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
      this.ClientSize = new System.Drawing.Size(592, 349);
      this.Controls.AddRange(new System.Windows.Forms.Control[] {
                                                                  this.mList});
      this.Name = "UndoListView";
      this.Text = "Undo List";
      this.Layout += new System.Windows.Forms.LayoutEventHandler(this.UndoListView_HandleLayout);
      this.ResumeLayout(false);

    }
		#endregion

    private void UndoListView_HandleLayout(object sender, LayoutEventArgs e)
    {
      mList.SetBounds(0,0,this.ClientSize.Width,this.ClientSize.Height);
      ResetColumns();
    }
    private void ResetColumns()
    {
      mList.Columns.Clear();
      mList.Columns.Add("List Name", 0, HorizontalAlignment.Left);
      mList.Columns.Add("Action", 0, HorizontalAlignment.Left);
      mList.Columns.Add("Name", 0, HorizontalAlignment.Left);
      mList.Columns.Add("Value", 0, HorizontalAlignment.Left);

      int width = mList.ClientSize.Width;
      mList.Columns[0].Width = 60;
      width -= mList.Columns[0].Width;
      
      mList.Columns[1].Width = 60;
      width -= mList.Columns[1].Width;
      
      mList.Columns[2].Width = 60;
      width -= mList.Columns[2].Width;

      mList.Columns[3].Width = width;
    }
  }
}

UndoMemento.cs

Synopsis
using System;
using System.IO;

namespace jEnvEditor
{
	/// <summary>
	/// Memento of an action to undo.
	/// </summary>
	public class UndoMemento
	{
    protected string mListName;
    protected string mAction;
    protected string mName;
    protected string mValue;
		public UndoMemento(string listname, string action, string name, string val)
		{
      mListName = listname;
      mAction = action;
      mName = name;
      mValue = val;
    }
    public string ListName
    {
      get { return mListName; }
    }
    public string Action
    {
      get { return mAction; }
    }
    public string Name
    {
      get { return mName; }
    }
    public string Value
    {
      get { return mValue; }
    }

    public bool Compare(UndoMemento other)
    {
      if (mListName != other.mListName) return false;
      if (mAction != other.mAction) return false;
      if (mName != other.mName) return false;
      if (mValue != other.mValue) return false;

      return true;
    }
    public void WriteOn(StreamWriter sw)
    {
      sw.WriteLine(mListName + ":" + mAction + ":" + mName + ":" + mValue);
    }
    public static UndoMemento Parse(string line)
    {
      int lastposn = 0;
      int posn = line.IndexOf(':', lastposn);
      string listname = line.Substring(lastposn, posn - lastposn);
      lastposn = posn + 1;
      posn = line.IndexOf(":", lastposn);
      string action = line.Substring(lastposn, posn - lastposn);
      lastposn = posn + 1;
      posn = line.IndexOf(":", lastposn);
      string name = line.Substring(lastposn, posn - lastposn);
      lastposn = posn + 1;
      string val = line.Substring(lastposn);
      return new UndoMemento(listname, action, name, val);
    }
    public string[] ToArray()
    {
      return new string[] {mListName, mAction, mName, mValue};
    }
	}
}

UnitTests.cs

Synopsis
using System;
using System.IO;
using ut;

namespace jEnvEditor
{
  /// <summary>
  /// Summary description for UnitTests.
  /// </summary>
  public class test_envEditor
  {
    private string fname = "utest.txt";
    
    public void test_push()
    {
      UndoList ul = new UndoList(fname);
      utx.assert(ul.Count, 0);
      ul.Push(new UndoMemento("user", "delete","name1", "value1"));
      utx.assert(ul.Count, 1);
    }
    public void test_empty()
    {
      UndoList ul = new UndoList(fname);
      utx.assert(ul.Count, 0);
      UndoMemento mem = ul.Pop();
      utx.assert(mem, null);
      utx.assert(ul.Count, 0);
    }
    public void test_pop()
    {
      UndoList ul = new UndoList(fname);
      utx.assert(ul.Count, 0);
      UndoMemento mem1 = new UndoMemento("user", "delete","name1", "value1");
      ul.Push(mem1);
      utx.assert(ul.Count, 1);
      UndoMemento mem = ul.Pop();
      utx.assert(ul.Count, 0);
      utx.assert(mem1.Compare(mem));
    }
    public void test_save()
    {
      File.Delete(fname);
      Populate();
      utx.assert(File.Exists(fname));
    }
    public void test_load()
    {
      File.Delete(fname);
      Populate();

      UndoList ul2 = new UndoList(fname);
      ul2.Load();
      utx.assert(ul2.Count, 2);
      UndoMemento mem = ul2.Pop();
      utx.assert(mem.Compare(new UndoMemento("user", "edit","name2", "value2")));
      mem = ul2.Pop();
      utx.assert(mem.Compare(new UndoMemento("user", "delete","name1", "value1")));
    }
    private void Populate()
    {
      UndoList ul = new UndoList(fname);
      ul.Push(new UndoMemento("user", "delete","name1", "value1"));
      ul.Push(new UndoMemento("user", "edit","name2", "value2"));
      ul.Save();
    }
  }
}

UserList.cs

Synopsis
using System;
using System.Windows.Forms;

namespace jEnvEditor
{
  /// <summary>
  /// The User environment variables
  /// </summary>
  class UserList : TwoColumnList
  {
    public UserList(ListView parent, UndoList ul)
      : base("user", parent, ul, RegistryWrapper.UserEnvVariablesKey())
    {
    }
  }
}

winnotifier.cs

Synopsis
using System;
using System.Runtime.InteropServices;

namespace jEnvEditor
{
  class Win32SDK
  {
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    private static extern int SendMessageTimeout(int hWnd, int msg,
      int wParam, String lParam, int flags,
      int timeout, ref int result);
    private const int HWND_BROADCAST = 0xFFFF;
    private const int WM_SETTINGCHANGE = 0x1A;
    private const int SMTO_ABORTIFHUNG = 0x02;

    public static void SendNotification()
    {
      int dwReturnValue = 0;
      int rc = SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
        "Environment", SMTO_ABORTIFHUNG, 5000, ref dwReturnValue);
    }

   
    private delegate string getcmdlineDelegate();
    private static getcmdlineDelegate func = new getcmdlineDelegate(getcmdline);

    public static string StartupDirectory
    {
      get 
      {
        string commandLine = func().Trim();
        if (commandLine[0] == '\"')
        {
          commandLine = commandLine.Substring(1, commandLine.IndexOf("\"", 1));
        }
        else
        {
          int ispace = commandLine.IndexOf(" ");
          if (ispace > 0)
            commandLine = commandLine.Substring(0, ispace);
        }
        return commandLine.Substring(0, commandLine.LastIndexOf('\\'));
      }
    }

    [ DllImport( "Kernel32.dll", CharSet=CharSet.Auto )] 
    private static extern IntPtr GetCommandLine();   
    internal static string getcmdline()
    {
      return Marshal.PtrToStringAuto( GetCommandLine() );
    }
  }
}






Contact me about content on this page using john_web-at-arrizza-dot-com
For Web Master or site problems contact: webadmin-at-arrizza-dot-com
Copyright John Arrizza (c) 2001-2010