C2021-026 Parent/Child applicability in RO Editor

This commit is contained in:
2021-07-29 18:28:12 +00:00
parent 697490d5bf
commit ce9e9e182e
16 changed files with 1103 additions and 263 deletions

View File

@@ -1,5 +1,5 @@
/*********************************************************************************************
* Copyright 2002 - Volian Enterprises, Inc. All rights reserved.
* Copyright 2021 - Volian Enterprises, Inc. All rights reserved.
* Volian Enterprises - Proprietary Information - DO NOT COPY OR DISTRIBUTE
* ------------------------------------------------------------------------------
* $Workfile: ctlXMLEdit.cs $ $Revision: 36 $
@@ -258,12 +258,17 @@ namespace ctlXMLEditLib
int DPPL = (720/6);
int DPPC = (720/12);
int height, width;
/** C2021-026 the following are use for Parent Child RO fields **/
public ArrayList FieldsWithApplic = null;
public string[] PCChildren;
private GroupBox pcGrpBox = null;
/** end C2021-026 **/
// use this struct to define attributes for the text box fields, storing
// the pattern, radio button association, required field flag, etc.
struct TextBoxAttrTag
{
bool required; //whether the field is required
string req_msg; //message to print if required, but not set
string pattern; //pattern for validation
@@ -295,10 +300,12 @@ namespace ctlXMLEditLib
public void SetImageDate(string imgdate) {this.imagedate = imgdate;}
}
public ctlXMLEdit(VlnXmlElement myelem, XmlSchema myschema, ArrayList reqfields)
public ctlXMLEdit(VlnXmlElement myelem, XmlSchema myschema, ArrayList reqfields, ArrayList fldsWithApplic, string [] pckids)
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
FieldsWithApplic = fldsWithApplic;
PCChildren = pckids; //C2021-026 list of Parent/Child children
zmtooltip = new ToolTip();
myHT = new Hashtable();
tabindx=0;
@@ -409,6 +416,38 @@ namespace ctlXMLEditLib
}
}
}
// C2021-026 If this is a Parent/Child field that has no value saved in the database
// then use the parent's value and display it as grey colored text.
private void GetDefaultParentValue(TextBox tb, XmlNode node, string chldName)
{
XmlNode parentNode = null;
// PCChildren contains a list strings reprenting the Children setup in the current Working Draft Parent/Child property
if (PCChildren == null) return; // C2021-026 no children to process
int pcChildIdx = 0; // C2021-026 corresponds with DocVersionConfig.SelectedSlave value: 0 = no child selected 1 = first child ...
foreach (string c in PCChildren)
{
pcChildIdx++;
string csufx = string.Format("_PCCHILD{0}", pcChildIdx); // C2021-026 create a child field name
if (chldName.EndsWith(csufx))
{
int idx = chldName.LastIndexOf(csufx);
if (idx > 0)
{
string parent = chldName.Remove(idx);
parentNode = node.SelectSingleNode(parent);
// if not found with just the string, search the tree.
if (parentNode == null) parentNode = node.SelectSingleNode("*/" + parent);
if (parentNode != null)
{
tb.Text = parentNode.InnerText; // set the P/C Child text box to the parent's value
tb.ForeColor = SystemColors.GrayText;
break;
}
}
}
}
}
// Given a parent XmlNode, walk through the child nodes & add the text for the
// node to the associated text box.
@@ -425,7 +464,9 @@ namespace ctlXMLEditLib
nd = node.SelectSingleNode(str);
// if not found with just the string, search the tree.
if (nd==null)nd = node.SelectSingleNode("*/"+str);
if (nd != null)
if (nd == null)
GetDefaultParentValue(hwnd, node, str); // C2021-026 Parent/Child Field has no value so use parent's value
else
{
hwnd.Text = nd.InnerText; // set the field's text from XML
@@ -504,8 +545,8 @@ namespace ctlXMLEditLib
{
// if MaxWidth is small, a scroll bar appears below the fields
// so make this a bit larger, so a scroll bar doesn't appear
if (MaxWidth<30) return MaxWidth+60;
return MaxWidth+30;
if (MaxWidth < 30) return MaxWidth + 100;
return MaxWidth + 70;
}
public int GetMaxLength()
{
@@ -569,11 +610,46 @@ namespace ctlXMLEditLib
editelem.InnerXml = savedInnerXml;
}
//C2021-026 when saving the RO record, if a PC Child's textbox contains a value identical
// to the parent's value, then clear the child's textbox so that nothing is saved
// to the database. This allow us to know that a specific value was not set
// for this Parent/Child child
private void RemovePCChildTextIfSameAsParent(XmlNode node, TextBox tb, string chldName)
{
XmlNode parentNode = null;
// if this is a child node get the parent's value
// PCChildren contains a list strings reprenting the Children setup in the current Working Draft Parent/Child property
if (PCChildren == null) return;
int pcChildIdx = 0;
foreach (string c in PCChildren)
{
//string csufx = CvtUserFldToFld(c);
pcChildIdx++;
string csufx = string.Format("_PCCHILD{0}", pcChildIdx);
if (chldName.EndsWith(csufx))
{
int idx = chldName.LastIndexOf(csufx);
if (idx > 0)
{
string parent = chldName.Remove(idx);
parentNode = node.SelectSingleNode(parent);
// if not found with just the string, search the tree.
if (parentNode == null) parentNode = node.SelectSingleNode("*/" + parent);
if (parentNode != null && parentNode.InnerText == tb.Text)
{
tb.Text = "";
break;
}
}
}
}
}
// SaveData saves the data in the element which had been sent to the control. Return
// true if success, false if fail.
// Note that the Parent and Child XML node variables below are not coding for Parent/Child Applicabily Fields
public bool SaveData()
{
if (mysavexml)
{
TextBox hwnd;
@@ -586,7 +662,6 @@ namespace ctlXMLEditLib
object o = myHT[str];
hwnd = (TextBox) o;
imgdate = null;
// if this is a required field and there is no text, put out an error
// message and get out of here.
if (hwnd.Tag != null)
@@ -602,7 +677,6 @@ namespace ctlXMLEditLib
return (false);
}
imgdate = tag.GetImageDate;
}
// find the element in the current element node.
@@ -612,7 +686,7 @@ namespace ctlXMLEditLib
XmlNode elmnode = (XmlNode) editelem;
XmlNode nd = elmnode.SelectSingleNode(str);
if (nd == null) nd = elmnode.SelectSingleNode("*/"+str);
RemovePCChildTextIfSameAsParent(elmnode, hwnd, str); // C2021-026 will clear hwnd.Text if child value is same as parent value
// handle, element exists - but text removed first (delete element)
if ((hwnd.Text == null || hwnd.Text == "") && nd != null)
{
@@ -694,6 +768,7 @@ namespace ctlXMLEditLib
}
}
mysavexml=false; // data has been saved, don't allow it again.
DisplayFieldContents((XmlNode) editelem); // to refresh display after saving Parent/Child fields to show default values
return(true);
}
return (false);
@@ -783,7 +858,8 @@ namespace ctlXMLEditLib
{
XmlSchemaDocumentation doc = (XmlSchemaDocumentation) item;
XmlNode[] node = (XmlNode[]) doc.Markup;
// Note: this has nothing to do with PROMS Annotations. This is more of a field type description
// used for Graphics (figures) RO fields to setup event handlers and buttons to display a Find File Dialog
getannot = node[0].InnerText;
if (getannot == "VLN_FINDFILE")
{
@@ -894,7 +970,6 @@ namespace ctlXMLEditLib
else
tmp = element.SchemaTypeName.Name;
radio.Text = CvtFldToUserFld(tmp);
//radio.Width = (int) radio.Font.SizeInPoints * radio.Text.Length + 20; // add 20 for button
radio.TabIndex = 0;
ysize = (int) radio.Height;
@@ -916,8 +991,20 @@ namespace ctlXMLEditLib
tb.KeyDown += new KeyEventHandler(MyOnKeyDown);
gbox.Contains(tb);
// the following will set attributes on the text boxes such as maxlength, multiline, etc.
DisplayXmlSchemaSimpleType((XmlSchemaSimpleType)element.SchemaType, tb, radio,false,null);
rety = (ysize + 25 + tb.Height);
DisplayXmlSchemaSimpleType((XmlSchemaSimpleType)element.SchemaType, tb, radio,false,null);
int chldGrpHeight = 0;
if (FieldsWithApplic != null && FieldsWithApplic.Contains(gbox.Text) && radio.Text == "Fixed") // C2021-026 user turned appicability on for this field
{
int saveScreeny = screeny;
int saveScreenx = screenx;
screeny += tb.Height + 50;
screenx += 20;
pcGrpBox = null; // C2021-026 used to hide/show Parent/Child group when radio buttons are selected
DisplayAppicChildrenGroup(element, PCChildren, ref chldGrpHeight, gbox.Text); // C2021-026 make sub-group for Parent/Child child fields (if needed)
screeny = saveScreeny;
screenx = saveScreenx;
}
rety = (ysize + 25 + chldGrpHeight + tb.Height);
retx = tb.Width;
}
@@ -956,25 +1043,84 @@ namespace ctlXMLEditLib
// get the widths of all children of this group box & use this to set the size
// of the groupbox.
int gritms = groupbox.Controls.Count;
screeny=screeny+maxyfortext+10;
screeny = screeny + maxyfortext + 20;
MaxWidth = (maxxfortext+40>MaxWidth)?maxxfortext+40:MaxWidth;
groupbox.Size = new System.Drawing.Size(maxxfortext+40, maxyfortext+10);
Controls.Add(groupbox);
}
private void DisplayXmlSchemaElement(XmlSchemaElement element)
{
string userfldName = CvtFldToUserFld(element.Name);
string childLabel = "";
bool pcApplic = FieldsWithApplic != null && FieldsWithApplic.Contains(userfldName); // C2021-026 returns True if field should show Parent/Child Applicability fields
if (pcApplic) childLabel = CvtFldToUserFld(element.Name);
int dmy = 0;
DoDisplayXmlSchemaElement(element, childLabel, 0, ref dmy, Color.Transparent, 0);
if (pcApplic)
{
// C2021-026 this will create a grouping containing Parent/Child Applicability fields
DisplayAppicChildrenGroup(element, PCChildren, ref dmy, null);
screeny += 10;
}
}
// C2021-026 Creates a group box containing Parent/Child Applicability fields
// the group box is indented and shaded a blue color
private void DisplayAppicChildrenGroup(XmlSchemaElement element, string [] PCChildren, ref int chldgrphgt, string altGrpName)
{
int screenposx, screenposy;
int savescreenX = screenx;
screenx += 20;
GroupBox groupbox = new GroupBox();
groupbox.BackColor = Color.AliceBlue;
groupbox.SuspendLayout();
groupbox.Location = new System.Drawing.Point(screenx, screeny);
groupbox.Name = "PCgb_" + element.Name;
groupbox.TabStop = false;
// remove the last character of the name for the title of the group box.
string tstr = (altGrpName == null)?CvtFldToUserFld(element.Name):altGrpName;//(elem.Name);
groupbox.Text = "Child Values";
screenposx = screenx + 20;
screenposy = screeny + 20;
int screenySave = screeny;
screeny += 20;
int maxChldWidth = 0;
int pcChildIdx = 0;
foreach (string s in PCChildren)
{
string childLabel = s;
pcChildIdx++;
DoDisplayXmlSchemaElement(element, childLabel, 20, ref maxChldWidth,Color.AliceBlue, pcChildIdx);
}
// get the widths and number of all children of this group box & use this to set the size
// of the groupbox.
groupbox.Size = new System.Drawing.Size(Math.Max(55,maxChldWidth + 40), screeny - screenySave + 5);//maxxfortext + 40, maxyfortext + 10);
chldgrphgt = screeny - screenySave + 5;
Controls.Add(groupbox);
if (pcGrpBox == null)
pcGrpBox = groupbox; // only save if is in a Choice (radio button) group - used to hide/unhide the P/C Group box when radio buttons are selected
screenx = savescreenX;
}
private void DoDisplayXmlSchemaElement(XmlSchemaElement element, string applicLabel, int indent, ref int maxwidth, Color chlbckcolor, int pcChildIdx)
{
// always add a label.
Label mylabel;
int sscreeny;
mylabel = new System.Windows.Forms.Label();
mylabel.Location = new Point(screenx, screeny);
mylabel.Name = element.Name;
mylabel.Text = CvtFldToUserFld(element.Name);
string userfldName = CvtFldToUserFld(element.Name);
string pcChildFldName = element.Name; // C2021-026 PC Child field name
// C2021-026 the first PC Child has pcChildIdx of one
if (pcChildIdx > 0)
pcChildFldName += string.Format("_PCCHILD{0}", pcChildIdx);
Label mylabel;
mylabel = new System.Windows.Forms.Label();
mylabel.BackColor = chlbckcolor; // PC Applic fields are shaded blue otherwise backcolor is transparent
mylabel.Location = new Point(screenx+indent, screeny);
mylabel.Name = (pcChildIdx == 0) ? CvtUserFldToFld(element.Name) : CvtUserFldToFld(pcChildFldName);
mylabel.Text = (applicLabel.Length > 0) ? applicLabel : CvtFldToUserFld(element.Name); // C2021-026 applicLabel is the P/C Child name
mylabel.AutoSize = true;
Controls.Add(mylabel);
// add 3 onto screeny so that textbox is slightly below label.
screeny = screeny+mylabel.Height+3;
screeny = screeny + mylabel.Height + 3;
sscreeny = screeny; // save 'y' location in case of annotation.
if (element.SchemaType != null && element.SchemaType is XmlSchemaComplexType)
{
@@ -986,23 +1132,34 @@ namespace ctlXMLEditLib
{
TextBox mytextbox;
mytextbox = new TextBox();
mytextbox.Location = new Point(screenx, screeny);
myHT.Add(element.Name,mytextbox);
mytextbox.Location = new Point(screenx+indent, screeny);
string tFieldName = (pcChildIdx == 0) ? CvtUserFldToFld(element.Name) : CvtUserFldToFld(pcChildFldName);
myHT.Add(tFieldName, mytextbox);
tabindx++;
Controls.Add(mytextbox);
screeny+=mytextbox.Height;
screeny = screeny + 10;
mytextbox.TextChanged += new System.EventHandler(this.textbox_change);
mytextbox.Validating += new System.ComponentModel.CancelEventHandler(this.textbox_Validating);
mytextbox.GotFocus += new System.EventHandler(this.textbox_zoombtn);
mytextbox.KeyDown += new KeyEventHandler(MyOnKeyDown);
if (pcChildIdx > 0)
{
mytextbox.Enter += new System.EventHandler(this.txtBox_Enter);
mytextbox.Leave += new System.EventHandler(this.txtBox_Leave);
}
string labelAnnot;
bool imgchld = false;
if (element.Name == "Image_Filename" || element.Name == "Image_Height" || element.Name == "Image_Width") imgchld = true;
// Pass the textbox in to set attributes such as maxlength, multiline and pattern
// DisplayXmlSchemaSimpleType will set up
// - the textbox length which is needed to determin the Parent/Child group box width
// - add special buttons and events for Graphic (figure) RO type fields
labelAnnot = DisplayXmlSchemaSimpleType((XmlSchemaSimpleType)element.SchemaType,mytextbox, null,imgchld,GraphicsText);
if (labelAnnot != null)
{
// this is part of a Graphics (figure) RO - either the height or width adjustment text box
// so put a lable next to the respective height/width text box
Label annot;
annot = new System.Windows.Forms.Label();
annot.Location = new Point(screenx+mytextbox.Width+10, sscreeny);
@@ -1011,7 +1168,9 @@ namespace ctlXMLEditLib
annot.AutoSize = true;
Controls.Add(annot);
}
screeny+=mytextbox.Height;
screeny += mytextbox.Height;
maxwidth = Math.Max(maxwidth, mylabel.Width); // is the label wider?
maxwidth = Math.Max(mytextbox.Width, maxwidth); // is the text box wider?
}
}
@@ -1028,6 +1187,37 @@ namespace ctlXMLEditLib
{
if(dosaveflag)mysavexml = true;
}
// C2021-026 Event handler for Parent/Child child textbox
// if the textbox text is same as parent, then or nothing is entered in the textbox
// then use the parent value and set the text color to gray
private void txtBox_Leave(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
string dfTxt = "";
string parName = pcGrpBox.Name.Substring(5);
object o = myHT[parName];
if (o != null)
dfTxt = (o as TextBox).Text; // set to use the parent's value (default)
if (dosaveflag) mysavexml = true;
if (tb.Text.Length == 0 || tb.Text == dfTxt)
{
tb.Text = dfTxt;
tb.ForeColor = SystemColors.GrayText;
}
}
// C2021-026 Event handler for Parent/Child child textbox
// If the textbox is set to gray, then we are using the parent value
// so clear the textbox so that user can enter the value for that child
private void txtBox_Enter(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
if (tb.ForeColor == SystemColors.GrayText) // currently no value set - using parent's value
{
tb.Text = "";
tb.ForeColor = SystemColors.WindowText;
}
}
// radiocheckchg - called when a radio button is selected. This will set
// visibility for associated text box.
@@ -1050,6 +1240,30 @@ namespace ctlXMLEditLib
assocbox = (TextBox) o;
// make the text box visible if checked, otherwise, invisible
assocbox.Visible = btnsel.Checked;
// C2021-026 show or hide the Parent/Child appicability group box
if (pcGrpBox != null) // note that we save only one applicability group box and only for the schema choice field type (radio buttons)
{
bool vsblState = (btnsel.Text == "Fixed"); // only show parent/child group if the Fixed radio button is selected
{
pcGrpBox.Visible = vsblState; // show or hide the P/C Children group box (the box shaded in blue)
// C2021-026 PCChildren contains a list strings reprenting the Children setup in the current Working Draft Parent/Child property
int pcChildIdx = 0;
foreach (string s in PCChildren)
{
pcChildIdx++;
string fldx = string.Format("_PCCHILD{0}", pcChildIdx); // create a field name for P/C Child fields
string tstr = pcGrpBox.Name.Substring(5) + fldx; // get the base part of the label and text box control name
foreach (Control c in Controls)
if (c.Name == tstr)
{
c.Visible = vsblState; // show or hide the lable inside the group box
object oo = myHT[c.Name];
if (oo != null)
(oo as TextBox).Visible = vsblState; // show or hide the associated text box
}
}
}
}
}
// these two methods convert user input field names from/to xml tags. (xml tags