/*
Copyright (c) 2002 Joe Gregorio
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.
*/
/*
[ 594650 ] Drop Down boxes allow direct entry.
Found by Eric Vitello. Fixed by Joe Gregorio
*/
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Xml;
namespace Bitworking{
/// <summary>
/// This forms constructs itself dynamically from an XML document description.
/// It also stores the results into a part of Aggie.xfg for the stylesheet to use
/// at a later date.
/// We only worry about two control types right now, an edit box and a drop-down select box.
/// When we read in a 'select' type option should create
/// a helper class that stores and name and the value.
/// The 'name' is returned bi ToString(), which is used by the
/// ComboBox to populate the list. The helper should also have
/// a ToValueString used to write out the value.
///
/// Should we keep a map, from controls to internal_name's?
/// </summary>
public class DynamicConfigForm : System.Windows.Forms.Form {
private const int yDelta = 16;
// The name, value pair for the items presented in a ComboBox.
private class SelectOptionInfo {
public string name_;
public string value_;
public SelectOptionInfo(string name, string value) {
name_ = name;
value_ = value;
}
public override bool Equals(Object obj) {
//Check for null and compare run-time types.
if (obj == null || GetType() != obj.GetType()) return false;
SelectOptionInfo rhs = (SelectOptionInfo)obj;
return (name_ == rhs.name_) && (value_ == rhs.value_);
}
public override int GetHashCode() {
return ((name_+value_).GetHashCode());
}
public override string ToString() {
return name_;
}
}
private string internal_template_name_;
private LinkLabel linkLabel_;
private LinkLabel helpLabel_;
private Hashtable controlInternalNameMap_;
public DynamicConfigForm(string StyleSheetDirName) {
FormBorderStyle = FormBorderStyle.FixedDialog;
controlInternalNameMap_ = new Hashtable();
//
// Required for Windows Form Designer support
//
InitializeComponent(StyleSheetDirName);
//
// TODO: Add any constructor code after InitializeComponent call
//
}
private string GetNodeContents(XmlNode root, string xpath, string defaultValue) {
string returnValue = defaultValue;
try {
XmlNode node = root.SelectSingleNode(xpath);
returnValue = node.InnerText;
}
catch (Exception) {
}
return returnValue;
}
private Control CreateLabel(Point loc, Size size, string value) {
Label label = new Label();
label.Location = loc;
label.Name = "label";
label.Size = size;
label.Text = value;
label.TextAlign = System.Drawing.ContentAlignment.BottomLeft;
Controls.Add(label);
return label;
}
private void InitializeComponent(string StyleSheetDirName) {
// Open the file
SuspendLayout();
XmlDocument xslConfig = new XmlDocument();
xslConfig.Load("templates/" + StyleSheetDirName + "/About.xml");
internal_template_name_ = GetNodeContents(xslConfig, "/template/internal_name", "unspecified_internal_name");
XmlDocument aggieConfig = new XmlDocument();
aggieConfig.Load("Aggie.xfg");
int yIndex = 8;
// Put the name, author name and link to address on the Dialog.
string templateName = GetNodeContents(xslConfig, "/template/name", "Unspecified Name");
string templateDescription = GetNodeContents(xslConfig, "/template/description", "Unspecified Description");
string author = GetNodeContents(xslConfig, "/template/author/name", "Author Name Unspecified");
string link = GetNodeContents(xslConfig, "/template/author/address", "");
string helpUrl = GetNodeContents(xslConfig, "/template/helpUrl", "");
CreateLabel(new System.Drawing.Point(8, yIndex), new System.Drawing.Size(450, 16), templateDescription);
yIndex += yDelta;
linkLabel_ = new LinkLabel();
linkLabel_.AutoSize = true;
linkLabel_.Location = new System.Drawing.Point(8, yIndex);
linkLabel_.Size = new System.Drawing.Size(250, 16);
linkLabel_.Text = author;
linkLabel_.Links.Add(0, author.Length, link);
Controls.Add(linkLabel_);
helpLabel_ = new LinkLabel();
helpLabel_.AutoSize = false;
helpLabel_.Location = new System.Drawing.Point(260, yIndex);
helpLabel_.Size = new System.Drawing.Size(190, 16);
helpLabel_.Text = "help";
helpLabel_.TextAlign = ContentAlignment.TopRight;
helpLabel_.Links.Add(0, 4, helpUrl);
Controls.Add(helpLabel_);
yIndex += 2*yDelta;
// Create an event handler for the LinkClicked event.
linkLabel_.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked);
helpLabel_.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_LinkClicked);
// Iterate over all the 'options'
XmlNodeList optionNodeList = xslConfig.SelectNodes("/template/options/option");
int tabIndex = 1;
foreach (XmlNode node in optionNodeList) {
string name = GetNodeContents(node, "name", "Unspecified Name");
string description = GetNodeContents(node, "description", "Unspecified Description");
string internal_option_name = GetNodeContents(node, "internal_name", "");
string defaultValue = GetNodeContents(node, "default", "");
string actualValue = null;
try {
actualValue = GetNodeContents(aggieConfig, "/AggieConfig/templates/" + internal_template_name_ + "/" + internal_option_name , "(Use the default value)");
}
catch (Exception) {
}
if ("(Use the default value)" == actualValue) {
actualValue = defaultValue;
}
// see if the control has a value already set in Aggie.xfg
// create a label for the description
CreateLabel(new System.Drawing.Point(8, yIndex), new System.Drawing.Size(450, 16), description);
yIndex += yDelta;
// create a label for the name
CreateLabel(new System.Drawing.Point(8, yIndex), new System.Drawing.Size(65, 16), name);
// create the right control (EditBox or ComboBox.)
Control control = null;
string controlType = node.Attributes["type"].InnerText;
if (controlType == "select") {
control = new ComboBox();
ComboBox combo = control as ComboBox;
combo.DropDownStyle = ComboBoxStyle.DropDownList;
XmlNodeList optionItems = node.SelectNodes("item");
// foreach <item>
foreach (XmlNode option in optionItems) {
// Create a SelectOptionInfo
SelectOptionInfo info = new SelectOptionInfo(option.InnerText, option.Attributes["value"].InnerText);
// Add it to the ComboBox
combo.Items.Add(info);
// Check if it is to be the selected value.
if (info.value_ == actualValue) {
combo.SelectedItem = info;
}
}
} else { // It must be an edit box.
control = new TextBox();
control.Text = actualValue;
}
control.Location = new System.Drawing.Point(75, yIndex);
control.Name = "control";
control.Size = new System.Drawing.Size(384, 16);
control.TabIndex = tabIndex++;
Controls.Add(control);
yIndex += yDelta;
yIndex += yDelta;
// add entry in a map from control to it's internal_name
controlInternalNameMap_.Add(control, internal_option_name);
}
yIndex += yDelta;
//
// okButton
//
Button okButton = new Button();
okButton.Location = new System.Drawing.Point(288, yIndex);
okButton.Name = "okButton";
okButton.Size = new System.Drawing.Size(88, 20);
okButton.TabIndex = 7;
okButton.Text = "Ok";
okButton.Click += new EventHandler(Ok_Clicked);
Controls.Add(okButton);
//
// cancelButton
//
Button cancelButton = new Button();
cancelButton.Location = new System.Drawing.Point(384, yIndex);
cancelButton.Name = "cancelButton";
cancelButton.Size = new System.Drawing.Size(88, 20);
cancelButton.TabIndex = 8;
cancelButton.Text = "Cancel";
cancelButton.Click += new EventHandler(Cancel_Clicked);
Controls.Add(cancelButton);
//
// Aggie Configuration
//
AutoScaleBaseSize = new System.Drawing.Size(5, 13);
ClientSize = new System.Drawing.Size(488, yIndex + yDelta + 20);
Name = "Template Configuration";
Text = templateName + "Template Configuration";
ResumeLayout(true);
}
private void linkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
// Display the appropriate link based on the value of the LinkData property of the Link object.
System.Diagnostics.Process.Start(e.Link.LinkData.ToString());
}
private void CreateTemplateNode(XmlDocument aggieConfig) {
XmlNode template = aggieConfig.SelectSingleNode("/AggieConfig/templates");
if (null == template) {
XmlElement elem = aggieConfig.CreateElement("templates");
aggieConfig.DocumentElement.AppendChild(elem);
}
template = aggieConfig.SelectSingleNode("/AggieConfig/templates");
XmlNode configInfo = aggieConfig.SelectSingleNode("/AggieConfig/templates/" + internal_template_name_);
if (null == configInfo) {
XmlElement elem = aggieConfig.CreateElement(internal_template_name_);
template.AppendChild(elem);
}
}
private void SetNodeContents(XmlDocument doc, XmlNode parent, string xpath, string value) {
XmlNode node = parent.SelectSingleNode(xpath);
if (null != node) {
node.InnerText = value;
} else {
XmlElement element = doc.CreateElement(xpath);
element.InnerText = value;
parent.AppendChild(element);
}
}
public void Ok_Clicked(object o, EventArgs ev) {
Cursor.Current = Cursors.WaitCursor;
XmlDocument aggieConfig = new XmlDocument();
aggieConfig.Load("Aggie.xfg");
CreateTemplateNode(aggieConfig);
XmlNode templateConfigInfo = aggieConfig.SelectSingleNode("/AggieConfig/templates/" + internal_template_name_);
foreach (DictionaryEntry pair in controlInternalNameMap_) {
ComboBox combo = pair.Key as ComboBox;
string controlValue = "";
if (null != combo) {
// Get the current selection.
SelectOptionInfo optInfo = combo.SelectedItem as SelectOptionInfo;
// Get the value, not the name.
if (null != optInfo && optInfo.value_ != null) {
controlValue = optInfo.value_ as string;
}
} else { // Must be a Text box.
TextBox textBox = pair.Key as TextBox;
controlValue = textBox.Text;
}
// Now stuff the control value into Aggie.xfg
string internal_option_name = pair.Value as string;
SetNodeContents(aggieConfig, templateConfigInfo, internal_option_name, controlValue);
}
aggieConfig.Save("Aggie.xfg");
Cursor.Current = Cursors.Default;
Close();
}
public void Cancel_Clicked(object o, EventArgs ev) {
Close();
}
}
}
|