public void HandleChildDeleted(IEditableUIControl childControl) { // if any of our children are deleted, we want to delete ourselves completely. // First, remove the child that was just deleted, and then delete all other controls and ourself foreach (IUIControl child in ChildControls) { if (child.Equals(childControl) == true) { ChildControls.Remove(child); break; } } HandleDelete(true); //// if we still have children //if( ChildControls.Count > 0 ) //{ // // update our layout // SetPosition( Frame.Left, Frame.Top ); //} //else //{ // // otherwise, delete ourselves and tell our parent // HandleDelete( true ); //} }
public void Destroy(object obj) { // release references to our UI objects if (ChildControls != null) { foreach (IUIControl uiControl in ChildControls) { uiControl.RemoveFromView(obj); } // and clear our UI list ChildControls.Clear( ); } if (UserNoteControls != null) { // remove (but don't destroy) the notes foreach (IUIControl uiControl in UserNoteControls) { uiControl.RemoveFromView(obj); } UserNoteControls.Clear(); } NoteXml = null; }
public void HandleDelete(bool notifyParent) { // first, delete all our child controls int i = 0; for (i = ChildControls.Count - 1; i >= 0; i--) { // since we DO support child controls that are containers, call HandleDelete on all our children IEditableUIControl editableControl = ChildControls[i] as IEditableUIControl; if (editableControl != null) { // let them know not to inform their parent, since that's us. editableControl.HandleDelete(false); } else { // if it's not editable, we need to remove it ourselves ChildControls[i].RemoveFromView(ParentEditingCanvas); } ChildControls.Remove(ChildControls[i]); } // clean ourselves up RemoveFromView(ParentEditingCanvas); // notify our parent if we need to if (notifyParent) { ParentNote.HandleChildDeleted(this); } }
public override void AddChildControl(Control child) { base.AddChildControl(child); if (ChildControls.IndexOf(child) == menuItemIndex) { child.Theme = themeSelected; } }
public void HandleChildDeleted(IEditableUIControl childControl) { // this allows direct children of ours to notify us they were deleted // (example: a user deletes the last word of text in a paragraph - the paragraph deletes itself, but Note must remove it from its ChildControls list.) foreach (IUIControl child in ChildControls) { if (child.Equals(childControl) == true) { ChildControls.Remove(child); break; } } }
public override void Update(double secondsElapsed, InputUtilities keyUtils, SharpDX.Vector2 cursorPoint, bool checkMouse = false) { base.Update(secondsElapsed, keyUtils, cursorPoint, checkMouse); if (this.Visible) { this.ContentLayout.ApplyLayout(this); float width = 0, height = 0; Control <SharpDXRenderer, Color, Vector2, TextFormat> lastControl = null; for (int i = 0; i < this.ChildControls.Count; i++) { var control = this.ChildControls[i]; if (!control.Visible) { continue; } lastControl = control; if (this.DynamicWidth) { if (control.Width + control.MarginLeft + control.MarginRight > width) { width = control.Width + control.MarginLeft + control.MarginRight; } } } if (this.DynamicHeight) { if (ChildControls.Count(x => x.Visible) > 0) { height = ChildControls.Where(x => x.Visible).Max(x => x.Y + x.Height); } } //if (lastControl != null) // height = lastControl.Y + lastControl.Height + lastControl.MarginBottom; if (this.DynamicWidth) { this.Width = width + this.MarginLeft + this.MarginRight; } if (this.DynamicHeight) { this.Height = height + this.MarginBottom; } } else { this.Height = 0; } }
// Takes a string and replaces the content of the paragraph with it. private void SetText(string text, string activeUrl) { foreach (IUIControl control in ChildControls) { control.RemoveFromView(ParentEditingCanvas); } ChildControls.Clear( ); // give the text a style that doesn't include things it shouldn't inherit Styles.Style textStyle = mStyle; textStyle.mBorderColor = null; textStyle.mBorderRadius = null; textStyle.mBorderWidth = null; // now break it into words so we can do word wrapping string[] words = text.Split(' '); foreach (string word in words) { // create labels out of each one if (string.IsNullOrEmpty(word) == false) { // if the last thing we added was a special control like a reveal box, we // need the first label after that to have a leading space so it doesn't bunch up against // the control string nextWord = word; NoteText wordLabel = Parser.CreateNoteText(new CreateParams(this, Frame.Width, Frame.Height, ref textStyle), nextWord + " "); ChildControls.Add(wordLabel); } } if (activeUrl.Trim( ) != EditableConfig.sPlaceholderUrlText && string.IsNullOrWhiteSpace(activeUrl) == false) { // help them out by adding 'https://' if it isn't there. if (activeUrl.StartsWith("https") == false && BibleRenderer.IsBiblePrefix(activeUrl) == false) { activeUrl = activeUrl.Insert(0, "https://"); } ActiveUrl = activeUrl; } else { ActiveUrl = null; } TryAddUrlGlyph(Frame.Width, Frame.Height); }
public string GetDeleteQuery() { string query = string.Empty; if (ControlDictionary == null || !ControlDictionary.Any()) { ControlDictionary = ChildControls.ToControlDictionary(); } foreach (var pair in ControlDictionary) { if (pair.Value is ILinesEnabled grid) { query += $"DELETE FROM {grid.TableName} WHERE {this.TableName}_id = (SELECT id FROM {this.TableName} WHERE STRFTIME('%Y%m%d', eb_created_at_device) < @strdate AND eb_synced <> {(int)DataSyncStatus.NotSynced});"; } } return(query + $"DELETE FROM {this.TableName} WHERE STRFTIME('%Y%m%d', eb_created_at_device) < @strdate AND eb_synced <> {(int)DataSyncStatus.NotSynced}; "); }
public void TryAddUrlGlyph(float parentWidth, float parentHeight) { if (string.IsNullOrEmpty(ActiveUrl) == false) { // give the text a style that doesn't include things it shouldn't inherit Styles.Style textStyle = mStyle; textStyle.mBorderColor = 0; textStyle.mBorderRadius = 0; textStyle.mBorderWidth = 0; textStyle.mFont.mColor = mStyle.mFont.mColor ?? ControlStyles.mText.mFont.mColor; textStyle.mFont.mName = PrivateControlStylingConfig.Icon_Font_Secondary; textStyle.mFont.mSize = mStyle.mFont.mSize ?? ControlStyles.mText.mFont.mSize; textStyle.mAlignment = Alignment.Right; NoteText wordLabel = Parser.CreateNoteText(new CreateParams(this, parentWidth, parentHeight, ref textStyle), PrivateNoteConfig.CitationUrl_Icon); ChildControls.Add(wordLabel); } }
public void AddControl(UserControl uc, List <Control> childlist) { if (ChildControls != null) { ChildControls.Add(uc); } else { ChildControls = new List <Control>() { uc } }; multiViewRestrict.ActiveViewIndex = 1; NoOfChildRestrictionSets = NoOfChildRestrictionSets + 1; pnlRestrictions.Controls.Add(uc); }
public void OnBroadcast(FocusEvent @event, FocusListener context, Control eventControl) { // 判断是不是其他监听器的消息(广播转发的时候其实已经过滤了,这句判断可以不加) if (context != this) { switch (@event) { case FocusEvent.Got: // 如果是其他监听器下的控件获得了焦点,且焦点最后的状态记录为true,则主动执行失去焦点的事件函数 if (isOnFocus && !ChildControls.Contains(eventControl)) { ChildControl_LostFocus(lastOnFocusControl, new EventArgs()); } break; case FocusEvent.Lost: break; } } }
//used public void AddControl(Control uc, List <Control> childlist = null) { if (ChildControls != null) { ChildControls.Add(uc); } else { ChildControls = new List <Control>() { uc } }; multiViewRestrict.ActiveViewIndex = 1; lnkAddActOrRes.Attributes.Add("name", hidRelativeId.Value + "-" + NoOfChildRestrictionSets); NoOfChildRestrictionSets = NoOfChildRestrictionSets + 1; pnlRestrictions.Controls.Add(uc); }
public void AddControls(List <Control> ucList, List <Control> childlist) { foreach (var uc in ucList) { if (ChildControls != null) { ChildControls.Add(uc); } else { ChildControls = new List <Control>() { uc } }; multiViewRestrict.ActiveViewIndex = 1; NoOfChildRestrictionSets = NoOfChildRestrictionSets + 1; pnlRestrictions.Controls.Add(uc); } }
public async Task UploadFiles(int RowId, WebformData WebFormData) { ControlDictionary = ChildControls.ToControlDictionary(); List <FileWrapper> Files = new List <FileWrapper>(); foreach (var pair in ControlDictionary) { if (pair.Value is EbMobileFileUpload) { string pattern = $"{this.TableName}-{RowId}-{pair.Value.Name}*"; Files.AddRange(HelperFunctions.GetFilesByPattern(pattern, pair.Value.Name)); } } if (Files.Count > 0) { var ApiFiles = await FormService.Instance.SendFilesAsync(Files); WebFormData.FillFromSendFileResp(Files, ApiFiles); } }
public string GetQuery() { List <string> colums = new List <string> { "eb_device_id", "eb_appversion", "eb_created_at_device", "eb_retry_count", "eb_loc_id", "id" }; if (ControlDictionary == null || !ControlDictionary.Any()) { ControlDictionary = ChildControls.ToControlDictionary(); } foreach (var pair in ControlDictionary) { if (!(pair.Value is INonPersistControl) && !(pair.Value is ILinesEnabled)) { colums.Add(pair.Value.Name); } } colums.Reverse(); return(string.Join(",", colums.ToArray())); }
public string Export( ) { string xmlExport = "<Note " + sDefaultNoteAttribs + ">"; // first, sort all controls by Y. That way, if something was created and then moved UP, it won't // have a negative value ChildControls.Sort(delegate(IUIControl a, IUIControl b) { if (a.GetFrame( ).Top < b.GetFrame( ).Top) { return(-1); } return(1); }); foreach (IUIControl child in ChildControls) { IEditableUIControl editableChild = child as IEditableUIControl; xmlExport += editableChild.Export(new RectangleF(Padding.Left, Padding.Top, 0, 0), 0); } xmlExport += "</Note>"; return(xmlExport); }
public DbTypedValue GetDbType(string name, object value, EbDbTypes type) { DbTypedValue TV = new DbTypedValue(name, value, type); EbMobileControl ctrl = ChildControls.Find(item => item.Name == name); if (ctrl != null) { TV.Type = ctrl.EbDbType; TV.Value = ctrl.SQLiteToActual(value); } else { if (type == EbDbTypes.Date) { TV.Value = Convert.ToDateTime(value).ToString("yyyy-MM-dd"); } else if (type == EbDbTypes.DateTime) { TV.Value = Convert.ToDateTime(value).ToString("yyyy-MM-dd HH:mm:ss"); } } return(TV); }
public void SetStyleValue(EditStyling.Style style, object value) { switch (style) { case EditStyling.Style.BoldParagraph: { // force all children to bold foreach (IUIControl child in ChildControls) { IEditableUIControl editableChild = child as IEditableUIControl; if (editableChild != null) { editableChild.SetStyleValue(EditStyling.Style.FontName, EditableParagraph.sDefaultBoldFontName); } } break; } case EditStyling.Style.BoldItalicizeParagraph: { // force all children to bold foreach (IUIControl child in ChildControls) { IEditableUIControl editableChild = child as IEditableUIControl; if (editableChild != null) { editableChild.SetStyleValue(EditStyling.Style.FontName, EditableParagraph.sDefaultBoldItalicFontName); } } break; } case EditStyling.Style.ItalicizeParagraph: { // force all children to bold foreach (IUIControl child in ChildControls) { IEditableUIControl editableChild = child as IEditableUIControl; if (editableChild != null) { editableChild.SetStyleValue(EditStyling.Style.FontName, EditableParagraph.sDefaultItalicFontName); } } break; } case EditStyling.Style.BulletParagraph: { // create a noteText with the bullet, and then insert it XmlTextReader reader = new XmlTextReader(new StringReader("<NT>" + sBulletChar + "</NT>")); reader.Read( ); IUIControl bulletText = Parser.TryParseControl(new CreateParams(this, ParentSize.Width, ParentSize.Height, ref mStyle), reader); ChildControls.Insert(0, bulletText); SetPosition(Frame.Left, Frame.Top); bulletText.AddToView(ParentEditingCanvas); break; } case EditStyling.Style.UnderlineParagraph: { // to underline the whole thing, we need to make it one big NoteText. // we'll gather all the text, convert it to a single NoteText with Underlined Attribute, // remove the existing children, and replace them with the new single underlined one. // get the full text. we can use the build HTML stream code to do this. string htmlStream = string.Empty; string textStream = string.Empty; BuildHTMLContent(ref htmlStream, ref textStream, new List <IUIControl>( )); // if the last character is a URL glyph, remove it textStream = textStream.Trim(new char[] { ' ', PrivateNoteConfig.CitationUrl_Icon[0] }); XmlTextReader reader = new XmlTextReader(new StringReader("<NT Underlined=\"True\">" + textStream + "</NT>")); reader.Read( ); IUIControl noteText = Parser.TryParseControl(new CreateParams(this, ParentSize.Width, ParentSize.Height, ref mStyle), reader); foreach (IUIControl control in ChildControls) { control.RemoveFromView(ParentEditingCanvas); } ChildControls.Clear( ); ChildControls.Add(noteText); SetPosition(Frame.Left, Frame.Top); noteText.AddToView(ParentEditingCanvas); break; } } }
public Paragraph(CreateParams parentParams, XmlReader reader) { Initialize( ); // Always get our style first mStyle = parentParams.Style; Styles.Style.ParseStyleAttributesWithDefaults(reader, ref mStyle, ref ControlStyles.mParagraph); // check for attributes we support RectangleF bounds = new RectangleF( ); SizeF parentSize = new SizeF(parentParams.Width, parentParams.Height); ParseCommonAttribs(reader, ref parentSize, ref bounds); // Get margins and padding RectangleF padding; RectangleF margin; GetMarginsAndPadding(ref mStyle, ref parentSize, ref bounds, out margin, out padding); // apply margins to as much of the bounds as we can (bottom must be done by our parent container) ApplyImmediateMargins(ref bounds, ref margin, ref parentSize); Margin = margin; // check for border styling int borderPaddingPx = 0; if (mStyle.mBorderColor.HasValue) { BorderView.BorderColor = mStyle.mBorderColor.Value; } if (mStyle.mBorderRadius.HasValue) { BorderView.CornerRadius = mStyle.mBorderRadius.Value; } if (mStyle.mBorderWidth.HasValue) { BorderView.BorderWidth = mStyle.mBorderWidth.Value; borderPaddingPx = (int)Rock.Mobile.Graphics.Util.UnitToPx(mStyle.mBorderWidth.Value + PrivateNoteConfig.BorderPadding); } if (mStyle.mBackgroundColor.HasValue) { BorderView.BackgroundColor = mStyle.mBackgroundColor.Value; } // // now calculate the available width based on padding. (Don't actually change our width) float availableWidth = bounds.Width - padding.Left - padding.Width - (borderPaddingPx * 2); // see if there's a URL we should care about ActiveUrl = reader.GetAttribute("Url"); string urlLaunchesExternalBrowser = reader.GetAttribute("UrlLaunchesExternalBrowser"); if (string.IsNullOrEmpty(urlLaunchesExternalBrowser) == false) { UrlLaunchesExternalBrowser = bool.Parse(urlLaunchesExternalBrowser); } string urlUsesRockImpersonation = reader.GetAttribute("UrlUsesRockImpersonation"); if (string.IsNullOrEmpty(urlUsesRockImpersonation) == false) { UrlUsesRockImpersonation = bool.Parse(urlUsesRockImpersonation); } // now read what our children's alignment should be // check for alignment string result = reader.GetAttribute("ChildAlignment"); if (string.IsNullOrEmpty(result) == false) { switch (result) { case "Left": { ChildHorzAlignment = Alignment.Left; break; } case "Right": { ChildHorzAlignment = Alignment.Right; break; } case "Center": { ChildHorzAlignment = Alignment.Center; break; } default: { ChildHorzAlignment = mStyle.mAlignment.Value; break; } } } else { // if it wasn't specified, use LEFT alignment. ChildHorzAlignment = Alignment.Left; } bool removedLeadingWhitespace = false; bool lastControlWasElement = false; bool finishedReading = false; while (finishedReading == false && reader.Read( )) { switch (reader.NodeType) { case XmlNodeType.Element: { IUIControl control = Parser.TryParseControl(new CreateParams(this, availableWidth, parentParams.Height, ref mStyle), reader); if (control != null) { // if the last control was an element (NoteText or Reveal), then we have two in a row. So place a space between them! if (lastControlWasElement) { NoteText textLabel = Parser.CreateNoteText(new CreateParams(this, availableWidth, parentParams.Height, ref mStyle), " "); ChildControls.Add(textLabel); } // only allow RevealBoxes / NoteText as children. if (control as RevealBox == null && control as NoteText == null) { throw new Exception(String.Format("Paragraph only supports children of type <RevealBox> or <NoteText>. Found <{0}>", control.GetType( ))); } ChildControls.Add(control); // flag that whitespace is removed, because either // this was the first control and we didn't want to, or // it was removed by the first text we created. removedLeadingWhitespace = true; // flag that the last control placed was a reveal, so that // should we come across another one immediately, we know to insert a space // so they don't render concatenated. lastControlWasElement = true; } break; } case XmlNodeType.Text: { // give the text a style that doesn't include things it shouldn't inherit Styles.Style textStyle = mStyle; textStyle.mBorderColor = null; textStyle.mBorderRadius = null; textStyle.mBorderWidth = null; // grab the text. remove any weird characters string text = Regex.Replace(reader.Value, @"\t|\n|\r", ""); if (removedLeadingWhitespace == false) { removedLeadingWhitespace = true; text = text.TrimStart(' '); } // now break it into words so we can do word wrapping string[] words = text.Split(' '); foreach (string word in words) { // create labels out of each one if (string.IsNullOrEmpty(word) == false) { // if the last thing we added was a special control like a reveal box, we // need the first label after that to have a leading space so it doesn't bunch up against // the control string nextWord = word; if (lastControlWasElement) { nextWord = word.Insert(0, " "); lastControlWasElement = false; } NoteText wordLabel = Parser.CreateNoteText(new CreateParams(this, availableWidth, parentParams.Height, ref textStyle), nextWord + " "); ChildControls.Add(wordLabel); } } lastControlWasElement = false; break; } case XmlNodeType.EndElement: { // if we hit the end of our label, we're done. //if( reader.Name == "Paragraph" || reader.Name == "P" ) if (ElementTagMatches(reader.Name)) { finishedReading = true; } break; } } } // should we add a URL Glyph? We're gonna be clever and add it AS a NoteText, so that it integrates with the paragraph nicely. // now add our glyph, if relevant TryAddUrlGlyph(availableWidth, parentParams.Height); // layout all controls // paragraphs are tricky. // We need to lay out controls horizontally and wrap when we run out of room. // To align, we need to keep track of each "row". When the row is full, // we calculate its width, and then adjust each item IN that row so // that the row is centered within the max width of the paragraph. // The max width of the paragraph is defined as the widest row. // maintain a list of all our rows so that once they are all generated, // we can align them based on the widest row. float maxRowWidth = 0; List <List <IUIControl> > rowList = new List <List <IUIControl> >( ); // track where within a row we need to start a control float rowRemainingWidth = availableWidth; float startingX = bounds.X + padding.Left + borderPaddingPx; // always store the last placed control's height so that should // our NEXT control need to wrap, we know how far down to wrap. float yOffset = bounds.Y + padding.Top + borderPaddingPx; float lastControlHeight = 0; float rowWidth = 0; //Create our first row and put it in our list List <IUIControl> currentRow = new List <IUIControl>( ); rowList.Add(currentRow); foreach (IUIControl control in ChildControls) { RectangleF controlFrame = control.GetFrame( ); // if there is NOT enough room on this row for the next control if (rowRemainingWidth < controlFrame.Width) { // since we're advancing to the next row, trim leading white space, which, if we weren't wrapping, // would be a space between words. // note: we can safely cast to a NoteText because that's the only child type we allow. string text = ((NoteText)control).GetText( ).TrimStart(' '); ((NoteText)control).SetText(text); // advance to the next row yOffset += lastControlHeight; // Reset values for the new row rowRemainingWidth = availableWidth; startingX = bounds.X + padding.Left + borderPaddingPx; lastControlHeight = 0; rowWidth = 0; currentRow = new List <IUIControl>( ); rowList.Add(currentRow); } // Add this next control to the current row currentRow.Add(control); // position this control appropriately control.AddOffset(startingX, yOffset); // update so the next child begins beyond this one. // also reduce the available width by this control's. rowWidth += controlFrame.Width; startingX += controlFrame.Width; //Increment startingX so the next control is placed after this one. rowRemainingWidth -= controlFrame.Width; //Reduce the available width by what this control took. lastControlHeight = controlFrame.Height > lastControlHeight ? controlFrame.Height : lastControlHeight; //Store the height of the tallest control on this row. // track the widest row maxRowWidth = rowWidth > maxRowWidth ? rowWidth : maxRowWidth; } // give each row the legal bounds it may work with RectangleF availableBounds = new RectangleF(bounds.X + padding.Left + borderPaddingPx, bounds.Y + borderPaddingPx + padding.Top, availableWidth, bounds.Height); // Now that we know the widest row, align all the rows foreach (List <IUIControl> row in rowList) { AlignRow(availableBounds, row, maxRowWidth); } // Build our final frame that determines our dimensions RectangleF frame = new RectangleF(65000, 65000, -65000, -65000); // for each child control foreach (IUIControl control in ChildControls) { // enlarge our frame by the current frame and the next child frame = Parser.CalcBoundingFrame(frame, control.GetFrame( )); } frame.Y = bounds.Y; frame.X = bounds.X; frame.Height += padding.Height + padding.Top + (borderPaddingPx * 2); //add in padding frame.Width = bounds.Width; // setup our bounding rect for the border frame = new RectangleF(frame.X, frame.Y, frame.Width, frame.Height); // and store that as our bounds BorderView.Frame = frame; Frame = frame; SetDebugFrame(Frame); // sort everything ChildControls.Sort(BaseControl.Sort); }
public void HandleChildStyleChanged(EditStyling.Style style, IEditableUIControl childControl) { switch (style) { case EditStyling.Style.RevealBox: { // first, find the target in our list int targetIndex = 0; foreach (IUIControl child in ChildControls) { // when we find it if (child.Equals(childControl) == true) { // take its index, and remove it from the renderer and our list of children targetIndex = ChildControls.IndexOf(child); child.RemoveFromView(ParentEditingCanvas); ChildControls.RemoveAt(targetIndex); break; } } // if we received RevealBox, we're either upgrading a NoteText to BE a RevealBox, // or downgrading a RevealBox to be a normal NoteText. EditableNoteText editableNoteText = childControl as EditableNoteText; if (editableNoteText != null) { // create a new revealBox, but force the text to uppper-case and add the bold font (since this is typically what the Mobile App does) Style controlStyle = childControl.GetControlStyle( ); controlStyle.mFont = new FontParams( ); controlStyle.mFont.mName = sDefaultBoldFontName; RevealBox newRevealBox = Parser.CreateRevealBox(new CreateParams(this, Frame.Width, Frame.Height, ref controlStyle), editableNoteText.GetText( ).ToUpper( ).Trim( )); newRevealBox.AddToView(ParentEditingCanvas); // add the new revealBox into the same spot as what it's replacing ChildControls.Insert(targetIndex, newRevealBox); // make sure we add a space after the reveal box, as that's required. NoteText textLabel = Parser.CreateNoteText(new CreateParams(this, Frame.Width, Frame.Height, ref mStyle), " "); textLabel.AddToView(ParentEditingCanvas); ChildControls.Insert(targetIndex + 1, textLabel); } EditableRevealBox editableRevealBox = childControl as EditableRevealBox; if (editableRevealBox != null) { // create a new revealBox that has the styling and text of the noteText it's replacing. Style controlStyle = childControl.GetControlStyle( ); NoteText newNoteText = Parser.CreateNoteText(new CreateParams(this, Frame.Width, Frame.Height, ref controlStyle), editableRevealBox.GetText( ).Trim( )); newNoteText.AddToView(ParentEditingCanvas); // add the new revealBox into the same spot as what it's replacing ChildControls.Insert(targetIndex, newNoteText); } break; } } // for now, lets just redo our layout. SetPosition(Frame.Left, Frame.Top); }
public override void LoadContent(ContentManager content, bool loadChildrenContent = false) { base.LoadContent(content, loadChildrenContent); ChildControls.LoadContent(content, loadChildrenContent); }
public Canvas(CreateParams parentParams, XmlReader reader) { Initialize( ); // Always get our style first mStyle = parentParams.Style; Styles.Style.ParseStyleAttributesWithDefaults(reader, ref mStyle, ref ControlStyles.mCanvas); // check for attributes we support RectangleF bounds = new RectangleF( ); SizeF parentSize = new SizeF(parentParams.Width, parentParams.Height); ParseCommonAttribs(reader, ref parentSize, ref bounds); // Get margins and padding RectangleF padding; RectangleF margin; GetMarginsAndPadding(ref mStyle, ref parentSize, ref bounds, out margin, out padding); // apply margins to as much of the bounds as we can (bottom must be done by our parent container) ApplyImmediateMargins(ref bounds, ref margin, ref parentSize); Margin = margin; // check for border styling int borderPaddingPx = 0; if (mStyle.mBorderColor.HasValue) { BorderView.BorderColor = mStyle.mBorderColor.Value; } if (mStyle.mBorderRadius.HasValue) { BorderView.CornerRadius = mStyle.mBorderRadius.Value; } if (mStyle.mBorderWidth.HasValue) { BorderView.BorderWidth = mStyle.mBorderWidth.Value; borderPaddingPx = (int)Rock.Mobile.Graphics.Util.UnitToPx(mStyle.mBorderWidth.Value + PrivateNoteConfig.BorderPadding); } if (mStyle.mBackgroundColor.HasValue) { BorderView.BackgroundColor = mStyle.mBackgroundColor.Value; } // // now calculate the available width based on padding. (Don't actually change our width) float availableWidth = bounds.Width - padding.Left - padding.Width - (borderPaddingPx * 2); // now read what our children's alignment should be // check for alignment string result = reader.GetAttribute("ChildAlignment"); if (string.IsNullOrEmpty(result) == false) { switch (result) { case "Left": ChildHorzAlignment = Alignment.Left; break; case "Right": ChildHorzAlignment = Alignment.Right; break; case "Center": ChildHorzAlignment = Alignment.Center; break; default: ChildHorzAlignment = mStyle.mAlignment.Value; break; } } else { // if it wasn't specified, use OUR alignment. ChildHorzAlignment = mStyle.mAlignment.Value; } // Parse Child Controls bool finishedParsing = false; while (finishedParsing == false && reader.Read( )) { switch (reader.NodeType) { case XmlNodeType.Element: { // let each child have our available width. Style style = new Style( ); style = mStyle; style.mAlignment = ChildHorzAlignment; IUIControl control = Parser.TryParseControl(new CreateParams(this, availableWidth, parentParams.Height, ref style), reader); if (control != null) { ChildControls.Add(control); } break; } case XmlNodeType.EndElement: { // if we hit the end of our label, we're done. //if( reader.Name == "Canvas" || reader.Name == "C" ) if (ElementTagMatches(reader.Name)) { finishedParsing = true; } break; } } } // layout all controls float yOffset = bounds.Y + padding.Top + borderPaddingPx; //vertically they should just stack float height = 0; // now we must center each control within the stack. foreach (IUIControl control in ChildControls) { RectangleF controlFrame = control.GetFrame( ); RectangleF controlMargin = control.GetMargin( ); // horizontally position the controls according to their // requested alignment Alignment controlAlignment = control.GetHorzAlignment( ); // adjust by our position float xAdjust = 0; switch (controlAlignment) { case Alignment.Center: xAdjust = bounds.X + ((availableWidth / 2) - (controlFrame.Width / 2)); break; case Alignment.Right: xAdjust = bounds.X + (availableWidth - (controlFrame.Width + controlMargin.Width)); break; case Alignment.Left: xAdjust = bounds.X; break; } // adjust the next sibling by yOffset control.AddOffset(xAdjust + padding.Left + borderPaddingPx, yOffset); // track the height of the grid by the control lowest control height = (control.GetFrame( ).Bottom + +controlMargin.Height) > height ? (control.GetFrame( ).Bottom + +controlMargin.Height) : height; } // we need to store our bounds. We cannot // calculate them on the fly because we // would lose any control defined offsets, which would throw everything off. bounds.Height = height + padding.Height + borderPaddingPx; // setup our bounding rect for the border bounds = new RectangleF(bounds.X, bounds.Y, bounds.Width, bounds.Height); // and store that as our bounds BorderView.Frame = bounds; Frame = bounds; // store our debug frame SetDebugFrame(Frame); // sort everything ChildControls.Sort(BaseControl.Sort); }
void ParseNote(XmlReader reader, float parentWidthUnits, float parentHeightUnits) { DeviceHeight = parentHeightUnits; // get the style first Styles.Style.ParseStyleAttributesWithDefaults(reader, ref mStyle, ref ControlStyles.mMainNote); // check for attributes we support RectangleF bounds = new RectangleF( ); SizeF parentSize = new SizeF(parentWidthUnits, parentHeightUnits); Parser.ParseBounds(reader, ref parentSize, ref bounds); // Parent note doesn't support margins. // PADDING float leftPadding = Styles.Style.GetValueForNullable(mStyle.mPaddingLeft, parentWidthUnits, 0); float rightPadding = Styles.Style.GetValueForNullable(mStyle.mPaddingRight, parentWidthUnits, 0); float topPadding = Styles.Style.GetValueForNullable(mStyle.mPaddingTop, parentHeightUnits, 0); float bottomPadding = Styles.Style.GetValueForNullable(mStyle.mPaddingBottom, parentHeightUnits, 0); Padding = new RectangleF(leftPadding, rightPadding, topPadding, bottomPadding); // now calculate the available width based on padding. (Don't actually change our width) float availableWidth = parentWidthUnits - leftPadding - rightPadding; // A "special" (we won't call this a hack) attribute that will enable the user // to have a header container that spans the full width of the note, which allows // it to be unaffected by the padding. string result = reader.GetAttribute("FullWidthHeader"); if (string.IsNullOrEmpty(result) == false) { mStyle.mFullWidthHeader = bool.Parse(result); } // begin reading the xml stream bool finishedReading = false; while (finishedReading == false && reader.Read( )) { switch (reader.NodeType) { case XmlNodeType.Element: { float workingWidth = availableWidth; if (Header.ElementTagMatches(reader.Name) == true && mStyle.mFullWidthHeader == true) { workingWidth = parentWidthUnits; } IUIControl control = Parser.TryParseControl(new BaseControl.CreateParams(this, workingWidth, parentHeightUnits, ref mStyle), reader); ChildControls.Add(control); break; } case XmlNodeType.EndElement: { if (reader.Name == "Note") { finishedReading = true; } break; } } } // lay stuff out vertically. If the notes were built by hand, like a stackPanel. // if not by hand, like a canvas. float noteHeight = bounds.Y + topPadding; foreach (IUIControl control in ChildControls) { RectangleF controlFrame = control.GetFrame( ); RectangleF controlMargin = control.GetMargin( ); // horizontally position the controls according to their // requested alignment Alignment controlAlignment = control.GetHorzAlignment( ); // adjust by our position float xAdjust = 0; switch (controlAlignment) { case Alignment.Center: { xAdjust = bounds.X + ((availableWidth / 2) - (controlFrame.Width / 2)); break; } case Alignment.Right: { xAdjust = bounds.X + (availableWidth - (controlFrame.Width + controlMargin.Width)); break; } case Alignment.Left: { xAdjust = bounds.X; break; } } // place this next control at yOffset. yOffset should be the current noteHeight, which makes each control relative to the one above it. float yOffset = noteHeight; // if it's the header and full width is specified, don't apply padding. if (control as Header != null && mStyle.mFullWidthHeader == true) { control.AddOffset(xAdjust, yOffset); } else { control.AddOffset(xAdjust + leftPadding, yOffset); } // update the note height noteHeight = control.GetFrame( ).Bottom + controlMargin.Height; } bounds.Width = parentWidthUnits; bounds.Height = (noteHeight - bounds.Y) + bottomPadding; Frame = bounds; AddControlsToView( ); }
protected void LayoutStackPanel(RectangleF bounds, float leftPadding, float topPadding, float availableWidth, float bottomPadding, float borderPaddingPx) { // layout all controls float yOffset = bounds.Y + topPadding + borderPaddingPx; //vertically they should just stack // now we must center each control within the stack. foreach (IUIControl control in ChildControls) { RectangleF controlFrame = control.GetFrame( ); RectangleF controlMargin = control.GetMargin( ); // horizontally position the controls according to their // requested alignment Alignment controlAlignment = control.GetHorzAlignment( ); // adjust by our position float xAdjust = 0; switch (controlAlignment) { case Alignment.Center: { xAdjust = bounds.X + ((availableWidth / 2) - (controlFrame.Width / 2)); break; } case Alignment.Right: { xAdjust = bounds.X + (availableWidth - (controlFrame.Width + controlMargin.Width)); break; } case Alignment.Left: { xAdjust = bounds.X; break; } } // adjust the next sibling by yOffset control.AddOffset(xAdjust + leftPadding + borderPaddingPx, yOffset); // and the next sibling must begin there yOffset = control.GetFrame( ).Bottom + controlMargin.Height; } // we need to store our bounds. We cannot // calculate them on the fly because we // would lose any control defined offsets, which would throw everything off. bounds.Height = (yOffset - bounds.Y) + bottomPadding + borderPaddingPx; // and store that as our bounds BorderView.Frame = bounds; Frame = bounds; // store our debug frame SetDebugFrame(Frame); // sort everything ChildControls.Sort(BaseControl.Sort); }
public ListItem(CreateParams parentParams, XmlReader reader) { // verify that our parent is a list. That's the only acceptable place for us. if ((parentParams.Parent as List) == null) { throw new Exception(string.Format("<ListItem> parent must be <List>. This <ListItem> parent is: <{0}>", parentParams.Parent.GetType())); } Initialize( ); // Always get our style first mStyle = parentParams.Style; Styles.Style.ParseStyleAttributesWithDefaults(reader, ref mStyle, ref ControlStyles.mListItem); mStyle.mAlignment = null; //don't use alignment // check for attributes we support RectangleF bounds = new RectangleF( ); SizeF parentSize = new SizeF(parentParams.Width, parentParams.Height); ParseCommonAttribs(reader, ref parentSize, ref bounds); //ignore positioning attributes. bounds = new RectangleF( ); bounds.Width = parentParams.Width; // Get margins and padding RectangleF padding; RectangleF margin; GetMarginsAndPadding(ref mStyle, ref parentSize, ref bounds, out margin, out padding); // apply margins to as much of the bounds as we can (bottom must be done by our parent container) ApplyImmediateMargins(ref bounds, ref margin, ref parentSize); Margin = margin; // check for border styling int borderPaddingPx = 0; if (mStyle.mBorderColor.HasValue) { BorderView.BorderColor = mStyle.mBorderColor.Value; } if (mStyle.mBorderRadius.HasValue) { BorderView.CornerRadius = mStyle.mBorderRadius.Value; } if (mStyle.mBorderWidth.HasValue) { BorderView.BorderWidth = mStyle.mBorderWidth.Value; borderPaddingPx = (int)Rock.Mobile.Graphics.Util.UnitToPx(mStyle.mBorderWidth.Value + PrivateNoteConfig.BorderPadding); } if (mStyle.mBackgroundColor.HasValue) { BorderView.BackgroundColor = mStyle.mBackgroundColor.Value; } // // now calculate the available width based on padding. (Don't actually change our width) float availableWidth = bounds.Width - padding.Left - padding.Width - (borderPaddingPx * 2); // Parse Child Controls bool finishedParsing = false; while (finishedParsing == false && reader.Read( )) { switch (reader.NodeType) { case XmlNodeType.Element: { // let each child have our available width. IUIControl control = Parser.TryParseControl(new CreateParams(this, availableWidth, parentParams.Height, ref mStyle), reader); if (control != null) { ChildControls.Add(control); } break; } case XmlNodeType.Text: { // grab the text. remove any weird characters string text = Regex.Replace(reader.Value, @"\t|\n|\r", ""); // now break it into words so we can do word wrapping string[] words = text.Split(' '); // the very very first word gets a bullet point! string sentence = ""; foreach (string word in words) { // create labels out of each one if (string.IsNullOrEmpty(word) == false) { sentence += word + " "; } } NoteText textLabel = Parser.CreateNoteText(new CreateParams(this, availableWidth, parentParams.Height, ref mStyle), sentence); ChildControls.Add(textLabel); break; } case XmlNodeType.EndElement: { // if we hit the end of our label, we're done. //if( reader.Name == "ListItem" || reader.Name == "LI" ) if (ElementTagMatches(reader.Name)) { finishedParsing = true; } break; } } } LayoutStackPanel(bounds, padding.Left, padding.Top, availableWidth, padding.Height, borderPaddingPx); }
public void HandleCreateControl(Type controlType, PointF mousePos) { do { // first, if we're creating a header, we need to make sure there isn't already one if (typeof(EditableHeader) == controlType) { List <IUIControl> headerControls = new List <IUIControl>( ); GetControlOfType <EditableHeader>(headerControls); // we found a header, so we're done. if (headerControls.Count > 0) { break; } } // now see if any child wants to create it IUIControl newControl = null; foreach (IUIControl control in ChildControls) { IEditableUIControl editableControl = control as IEditableUIControl; if (editableControl != null) { IEditableUIControl containerControl = editableControl.ContainerForControl(controlType, mousePos); if (containerControl != null) { newControl = containerControl.HandleCreateControl(controlType, mousePos); break; } } } // if a child handled it, we're done if (newControl != null) { break; } // it wasn't a header, and a child didn't create it, so we will. float availableWidth = Frame.Width - Padding.Right - Padding.Left; // if the control type is a header, we want to force it to position 0 float workingWidth = availableWidth; if (typeof(EditableHeader) == controlType) { mousePos = PointF.Empty; // and if its allowed, use the full width if (mStyle.mFullWidthHeader == true) { workingWidth = Frame.Width; } } newControl = Parser.CreateEditableControl(controlType, new BaseControl.CreateParams(this, workingWidth, DeviceHeight, ref mStyle)); ChildControls.Add(newControl); // add it to our renderable canvas newControl.AddToView(MasterView); // default it to where the click occurred newControl.AddOffset((float)mousePos.X, (float)mousePos.Y); // if the newly created control is the lower than all others, update the note height. // This lets us continue to build vertically if (newControl.GetFrame( ).Bottom > Frame.Height) { Frame = new RectangleF(Frame.Left, Frame.Top, Frame.Width, newControl.GetFrame( ).Bottom + Padding.Bottom); } }while(0 != 0); }
public StackPanel(CreateParams parentParams, XmlReader reader) { Initialize( ); // Always get our style first mStyle = parentParams.Style; Styles.Style.ParseStyleAttributesWithDefaults(reader, ref mStyle, ref ControlStyles.mStackPanel); // check for attributes we support RectangleF bounds = new RectangleF( ); SizeF parentSize = new SizeF(parentParams.Width, parentParams.Height); ParseCommonAttribs(reader, ref parentSize, ref bounds); // Get margins and padding RectangleF padding; RectangleF margin; GetMarginsAndPadding(ref mStyle, ref parentSize, ref bounds, out margin, out padding); // apply margins to as much of the bounds as we can (bottom must be done by our parent container) ApplyImmediateMargins(ref bounds, ref margin, ref parentSize); Margin = margin; // check for border styling int borderPaddingPx = 0; if (mStyle.mBorderColor.HasValue) { BorderView.BorderColor = mStyle.mBorderColor.Value; } if (mStyle.mBorderRadius.HasValue) { BorderView.CornerRadius = mStyle.mBorderRadius.Value; } if (mStyle.mBorderWidth.HasValue) { BorderView.BorderWidth = mStyle.mBorderWidth.Value; borderPaddingPx = (int)Rock.Mobile.Graphics.Util.UnitToPx(mStyle.mBorderWidth.Value + PrivateNoteConfig.BorderPadding); } if (mStyle.mBackgroundColor.HasValue) { BorderView.BackgroundColor = mStyle.mBackgroundColor.Value; } // // now calculate the available width based on padding. (Don't actually change our width) float availableWidth = bounds.Width - padding.Left - padding.Width - (borderPaddingPx * 2); // now read what our children's alignment should be // check for alignment string result = reader.GetAttribute("ChildAlignment"); if (string.IsNullOrEmpty(result) == false) { switch (result) { case "Left": { ChildHorzAlignment = Alignment.Left; break; } case "Right": { ChildHorzAlignment = Alignment.Right; break; } case "Center": { ChildHorzAlignment = Alignment.Center; break; } default: { ChildHorzAlignment = mStyle.mAlignment.Value; break; } } } else { // if it wasn't specified, use left alignment. ChildHorzAlignment = Alignment.Left; } // Parse Child Controls bool finishedParsing = false; while (finishedParsing == false && reader.Read( )) { switch (reader.NodeType) { case XmlNodeType.Element: { // let each child have our available width. Style style = new Style( ); style = mStyle; style.mAlignment = ChildHorzAlignment; IUIControl control = Parser.TryParseControl(new CreateParams(this, availableWidth, parentParams.Height, ref style), reader); if (control != null) { ChildControls.Add(control); } break; } case XmlNodeType.EndElement: { // if we hit the end of our label, we're done. //if( reader.Name == "StackPanel" || reader.Name == "SP" ) if (ElementTagMatches(reader.Name)) { finishedParsing = true; } break; } } } LayoutStackPanel(bounds, padding.Left, padding.Top, availableWidth, padding.Height, borderPaddingPx); }
public List(CreateParams parentParams, XmlReader reader) { Initialize( ); // Always get our style first mStyle = parentParams.Style; Styles.Style.ParseStyleAttributesWithDefaults(reader, ref mStyle, ref ControlStyles.mList); // check for attributes we support RectangleF bounds = new RectangleF( ); SizeF parentSize = new SizeF(parentParams.Width, parentParams.Height); ParseCommonAttribs(reader, ref parentSize, ref bounds); // Get margins and padding RectangleF padding; RectangleF margin; GetMarginsAndPadding(ref mStyle, ref parentSize, ref bounds, out margin, out padding); // apply margins to as much of the bounds as we can (bottom must be done by our parent container) ApplyImmediateMargins(ref bounds, ref margin, ref parentSize); Margin = margin; // check for border styling int borderPaddingPx = 0; if (mStyle.mBorderColor.HasValue) { BorderView.BorderColor = mStyle.mBorderColor.Value; } if (mStyle.mBorderRadius.HasValue) { BorderView.CornerRadius = mStyle.mBorderRadius.Value; } if (mStyle.mBorderWidth.HasValue) { BorderView.BorderWidth = mStyle.mBorderWidth.Value; borderPaddingPx = (int)Rock.Mobile.Graphics.Util.UnitToPx(mStyle.mBorderWidth.Value + PrivateNoteConfig.BorderPadding); } if (mStyle.mBackgroundColor.HasValue) { BorderView.BackgroundColor = mStyle.mBackgroundColor.Value; } // // convert indentation if it's a percentage float listIndentation = mStyle.mListIndention.Value; if (listIndentation < 1) { listIndentation = parentParams.Width * listIndentation; } // now calculate the available width based on padding. (Don't actually change our width) // also consider the indention amount of the list. float availableWidth = bounds.Width - padding.Left - padding.Width - listIndentation - (borderPaddingPx * 2); // parse for the desired list style. Default to Bullet if they didn't put anything. ListType = reader.GetAttribute("Type"); if (string.IsNullOrEmpty(ListType) == true) { ListType = ListTypeBullet; } // Parse Child Controls int numberedCount = 1; // don't force our alignment, borders, bullet style or indentation on children. Style style = new Style( ); style = mStyle; style.mAlignment = null; style.mListIndention = null; style.mListBullet = null; style.mBorderColor = null; style.mBorderRadius = null; style.mBorderWidth = null; bool finishedParsing = false; while (finishedParsing == false && reader.Read( )) { switch (reader.NodeType) { case XmlNodeType.Element: { // Create the prefix for this list item. string listItemPrefixStr = mStyle.mListBullet + " "; if (ListType == ListTypeNumbered) { listItemPrefixStr = numberedCount.ToString() + ". "; } NoteText textLabel = Parser.CreateNoteText(new CreateParams(this, availableWidth, parentParams.Height, ref style), listItemPrefixStr); ChildControls.Add(textLabel); // create our actual child, but throw an exception if it's anything but a ListItem. IUIControl control = Parser.TryParseControl(new CreateParams(this, availableWidth - textLabel.GetFrame().Width, parentParams.Height, ref style), reader); ListItem listItem = control as ListItem; if (listItem == null) { throw new Exception(String.Format("Only a <ListItem> may be a child of a <List>. Found element <{0}>.", control.GetType( ))); } // if it will actually use the bullet point, increment our count. if (listItem.ShouldShowBulletPoint() == true) { numberedCount++; } else { // otherwise give it a blank space, and keep our count the same. textLabel.SetText(" "); } // and finally add the actual list item. ChildControls.Add(control); break; } case XmlNodeType.EndElement: { // if we hit the end of our label, we're done. //if( reader.Name == "List" || reader.Name == "L" ) if (ElementTagMatches(reader.Name)) { finishedParsing = true; } break; } } } // layout all controls float xAdjust = bounds.X + listIndentation; float yOffset = bounds.Y + padding.Top + borderPaddingPx; //vertically they should just stack // we know each child is a NoteText followed by ListItem. So, lay them out // as: * - ListItem // * - ListItem foreach (IUIControl control in ChildControls) { // position the control control.AddOffset(xAdjust + padding.Left + borderPaddingPx, yOffset); RectangleF controlFrame = control.GetFrame( ); RectangleF controlMargin = control.GetMargin( ); // is this the item prefix? if ((control as NoteText) != null) { // and update xAdjust so the actual item starts after. xAdjust += controlFrame.Width; } else { // reset the values for the next line. xAdjust = bounds.X + listIndentation; yOffset = controlFrame.Bottom + controlMargin.Height; } } // we need to store our bounds. We cannot // calculate them on the fly because we // would lose any control defined offsets, which would throw everything off. bounds.Height = (yOffset - bounds.Y) + padding.Height + borderPaddingPx; Frame = bounds; BorderView.Frame = bounds; // store our debug frame SetDebugFrame(Frame); // sort everything ChildControls.Sort(BaseControl.Sort); }