Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Controls / Primitives / BulletDecorator.cs / 1 / BulletDecorator.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using MS.Internal; using MS.Utility; using MS.Internal.Documents; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Windows.Threading; using System.Windows.Documents; using System.Windows.Media; namespace System.Windows.Controls.Primitives { ////// BulletDecorator is used for decorating a generic content of type UIElement. /// Usually, the content is a text and the bullet is a glyph representing /// something similar to a checkbox or a radiobutton. /// Bullet property is used to decorate the content by aligning itself with the first line of the content text. /// public class BulletDecorator : Decorator { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// Default BulletDecorator constructor /// ////// Automatic determination of current Dispatcher. /// Use alternative constructor that accepts a Dispatcher for best performance. /// public BulletDecorator() : base() { } #endregion //-------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Properties ////// DependencyProperty for public static readonly DependencyProperty BackgroundProperty = Panel.BackgroundProperty.AddOwner(typeof(BulletDecorator), new FrameworkPropertyMetadata( (Brush)null, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// The Background property defines the brush used to fill the area within the BulletDecorator. /// public Brush Background { get { return (Brush)GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } ////// Bullet property is the first visual element in BulletDecorator visual tree. /// It should be aligned to BulletDecorator.Child which is the second visual child. /// ///public UIElement Bullet { get { return _bullet; } set { if (_bullet != value) { if (_bullet != null) { // notify the visual layer that the old bullet has been removed. RemoveVisualChild(_bullet); //need to remove old element from logical tree RemoveLogicalChild(_bullet); } _bullet = value; AddLogicalChild(value); // notify the visual layer about the new child. AddVisualChild(value); // If we decorator content exists we need to move it at the end of the visual tree UIElement child = Child; if (child != null) { RemoveVisualChild(child); AddVisualChild(child); } InvalidateMeasure(); } } } #endregion Properties //-------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods /// /// Returns enumerator to logical children. /// protected internal override IEnumerator LogicalChildren { get { if (_bullet == null) { return base.LogicalChildren; } if (Child == null) { return new SingleChildEnumerator(_bullet); } return new DoubleChildEnumerator(_bullet, Child); } } private class DoubleChildEnumerator : IEnumerator { internal DoubleChildEnumerator(object child1, object child2) { Debug.Assert(child1 != null, "First child should be non-null."); Debug.Assert(child2 != null, "Second child should be non-null."); _child1 = child1; _child2 = child2; } object IEnumerator.Current { get { switch (_index) { case 0: return _child1; case 1: return _child2; default: return null; } } } bool IEnumerator.MoveNext() { _index++; return _index < 2; } void IEnumerator.Reset() { _index = -1; } private int _index = -1; private object _child1; private object _child2; } ////// Override from UIElement /// protected override void OnRender(DrawingContext dc) { // Draw background in rectangle inside border. Brush background = this.Background; if (background != null) { dc.DrawRectangle(background, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height)); } } ////// Returns the Visual children count. /// protected override int VisualChildrenCount { get { return (Child == null ? 0 : 1) + (_bullet == null ? 0 : 1); } } ////// Returns the child at the specified index. /// protected override Visual GetVisualChild(int index) { if (index < 0 || index > VisualChildrenCount-1) { throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); } if (index == 0 && _bullet != null) { return _bullet; } return Child; } ////// Updates DesiredSize of the BulletDecorator. Called by parent UIElement. /// This is the first pass of layout. /// /// Constraint size is an "upper limit" that BulletDecorator should not exceed. ///BulletDecorator' desired size. protected override Size MeasureOverride(Size constraint) { Size bulletSize = new Size(); Size contentSize = new Size(); UIElement bullet = Bullet; UIElement content = Child; // If we have bullet we should measure it first if (bullet != null) { bullet.Measure(constraint); bulletSize = bullet.DesiredSize; } // If we have second child (content) we should measure it if (content != null) { Size contentConstraint = constraint; contentConstraint.Width = Math.Max(0.0, contentConstraint.Width - bulletSize.Width); content.Measure(contentConstraint); contentSize = content.DesiredSize; } Size desiredSize = new Size(bulletSize.Width + contentSize.Width, Math.Max(bulletSize.Height, contentSize.Height)); return desiredSize; } ////// BulletDecorator arranges its children - Bullet and Child. /// Bullet is aligned vertically with the center of the content's first line /// /// Size that BulletDecorator will assume to position children. protected override Size ArrangeOverride(Size arrangeSize) { UIElement bullet = Bullet; UIElement content = Child; double contentOffsetX = 0; double bulletOffsetY = 0; Size bulletSize = new Size(); // Arrange the bullet if exist if (bullet != null) { bullet.Arrange(new Rect(bullet.DesiredSize)); bulletSize = bullet.RenderSize; contentOffsetX = bulletSize.Width; } // Arrange the content if exist if (content != null) { // Helper arranges child and may substitute a child's explicit properties for its DesiredSize. // The actual size the child takes up is stored in its RenderSize. Size contentSize = arrangeSize; if (bullet != null) { contentSize.Width = Math.Max(content.DesiredSize.Width, arrangeSize.Width - bullet.DesiredSize.Width); contentSize.Height = Math.Max(content.DesiredSize.Height, arrangeSize.Height); } content.Arrange(new Rect(contentOffsetX, 0, contentSize.Width, contentSize.Height)); double centerY = GetFirstLineHeight(content) * 0.5d; bulletOffsetY += Math.Max(0d, centerY - bulletSize.Height * 0.5d); } // Re-Position the bullet if exist if (bullet != null && !DoubleUtil.IsZero(bulletOffsetY)) { bullet.Arrange(new Rect(0, bulletOffsetY, bullet.DesiredSize.Width, bullet.DesiredSize.Height)); } return arrangeSize; } #endregion Protected Methods //------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------- #region Private Methods // This method calculates the height of the first line if the element is TextBlock or FlowDocumentScrollViewer // Otherwise returns the element height private double GetFirstLineHeight(UIElement element) { // We need to find TextBlock/FlowDocumentScrollViewer if it is nested inside ContentPresenter // Common scenario when used in styles is that BulletDecorator content is a ContentPresenter UIElement text = FindText(element); ReadOnlyCollectionlr = null; if (text != null) { TextBlock textElement = ((TextBlock)text); if (textElement.IsLayoutDataValid) lr = textElement.GetLineResults(); } else { text = FindFlowDocumentScrollViewer(element); if (text != null) { TextDocumentView tdv = ((IServiceProvider)text).GetService(typeof(ITextView)) as TextDocumentView; if (tdv != null && tdv.IsValid) { ReadOnlyCollection cr = tdv.Columns; if (cr != null && cr.Count > 0) { ColumnResult columnResult = cr[0]; ReadOnlyCollection pr = columnResult.Paragraphs; if (pr != null && pr.Count > 0) { ContainerParagraphResult cpr = pr[0] as ContainerParagraphResult; if (cpr != null) { TextParagraphResult textParagraphResult = cpr.Paragraphs[0] as TextParagraphResult; if (textParagraphResult != null) { lr = textParagraphResult.Lines; } } } } } } } if (lr != null && lr.Count > 0) { Point ancestorOffset = new Point(); text.TransformToAncestor(element).TryTransform(ancestorOffset, out ancestorOffset); return lr[0].LayoutBox.Height + ancestorOffset.Y * 2d; } return element.RenderSize.Height; } private TextBlock FindText(Visual root) { TextBlock text = root as TextBlock; if (text != null) return text; ContentPresenter cp = root as ContentPresenter; if (cp != null) { if(VisualTreeHelper.GetChildrenCount(cp) == 1) return VisualTreeHelper.GetChild(cp, 0) as TextBlock; } return null; } private FlowDocumentScrollViewer FindFlowDocumentScrollViewer(Visual root) { FlowDocumentScrollViewer text = root as FlowDocumentScrollViewer; if (text != null) return text; ContentPresenter cp = root as ContentPresenter; if (cp != null) { if(VisualTreeHelper.GetChildrenCount(cp) == 1) return VisualTreeHelper.GetChild(cp, 0) as FlowDocumentScrollViewer; } return null; } #endregion //------------------------------------------------------------------- // // Private Memebers // //------------------------------------------------------------------- #region Private Members UIElement _bullet = null; #endregion Private Members } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using MS.Internal; using MS.Utility; using MS.Internal.Documents; using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Windows.Threading; using System.Windows.Documents; using System.Windows.Media; namespace System.Windows.Controls.Primitives { /// /// BulletDecorator is used for decorating a generic content of type UIElement. /// Usually, the content is a text and the bullet is a glyph representing /// something similar to a checkbox or a radiobutton. /// Bullet property is used to decorate the content by aligning itself with the first line of the content text. /// public class BulletDecorator : Decorator { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors ////// Default BulletDecorator constructor /// ////// Automatic determination of current Dispatcher. /// Use alternative constructor that accepts a Dispatcher for best performance. /// public BulletDecorator() : base() { } #endregion //-------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Properties ////// DependencyProperty for public static readonly DependencyProperty BackgroundProperty = Panel.BackgroundProperty.AddOwner(typeof(BulletDecorator), new FrameworkPropertyMetadata( (Brush)null, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// The Background property defines the brush used to fill the area within the BulletDecorator. /// public Brush Background { get { return (Brush)GetValue(BackgroundProperty); } set { SetValue(BackgroundProperty, value); } } ////// Bullet property is the first visual element in BulletDecorator visual tree. /// It should be aligned to BulletDecorator.Child which is the second visual child. /// ///public UIElement Bullet { get { return _bullet; } set { if (_bullet != value) { if (_bullet != null) { // notify the visual layer that the old bullet has been removed. RemoveVisualChild(_bullet); //need to remove old element from logical tree RemoveLogicalChild(_bullet); } _bullet = value; AddLogicalChild(value); // notify the visual layer about the new child. AddVisualChild(value); // If we decorator content exists we need to move it at the end of the visual tree UIElement child = Child; if (child != null) { RemoveVisualChild(child); AddVisualChild(child); } InvalidateMeasure(); } } } #endregion Properties //-------------------------------------------------------------------- // // Protected Methods // //-------------------------------------------------------------------- #region Protected Methods /// /// Returns enumerator to logical children. /// protected internal override IEnumerator LogicalChildren { get { if (_bullet == null) { return base.LogicalChildren; } if (Child == null) { return new SingleChildEnumerator(_bullet); } return new DoubleChildEnumerator(_bullet, Child); } } private class DoubleChildEnumerator : IEnumerator { internal DoubleChildEnumerator(object child1, object child2) { Debug.Assert(child1 != null, "First child should be non-null."); Debug.Assert(child2 != null, "Second child should be non-null."); _child1 = child1; _child2 = child2; } object IEnumerator.Current { get { switch (_index) { case 0: return _child1; case 1: return _child2; default: return null; } } } bool IEnumerator.MoveNext() { _index++; return _index < 2; } void IEnumerator.Reset() { _index = -1; } private int _index = -1; private object _child1; private object _child2; } ////// Override from UIElement /// protected override void OnRender(DrawingContext dc) { // Draw background in rectangle inside border. Brush background = this.Background; if (background != null) { dc.DrawRectangle(background, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height)); } } ////// Returns the Visual children count. /// protected override int VisualChildrenCount { get { return (Child == null ? 0 : 1) + (_bullet == null ? 0 : 1); } } ////// Returns the child at the specified index. /// protected override Visual GetVisualChild(int index) { if (index < 0 || index > VisualChildrenCount-1) { throw new ArgumentOutOfRangeException("index", index, SR.Get(SRID.Visual_ArgumentOutOfRange)); } if (index == 0 && _bullet != null) { return _bullet; } return Child; } ////// Updates DesiredSize of the BulletDecorator. Called by parent UIElement. /// This is the first pass of layout. /// /// Constraint size is an "upper limit" that BulletDecorator should not exceed. ///BulletDecorator' desired size. protected override Size MeasureOverride(Size constraint) { Size bulletSize = new Size(); Size contentSize = new Size(); UIElement bullet = Bullet; UIElement content = Child; // If we have bullet we should measure it first if (bullet != null) { bullet.Measure(constraint); bulletSize = bullet.DesiredSize; } // If we have second child (content) we should measure it if (content != null) { Size contentConstraint = constraint; contentConstraint.Width = Math.Max(0.0, contentConstraint.Width - bulletSize.Width); content.Measure(contentConstraint); contentSize = content.DesiredSize; } Size desiredSize = new Size(bulletSize.Width + contentSize.Width, Math.Max(bulletSize.Height, contentSize.Height)); return desiredSize; } ////// BulletDecorator arranges its children - Bullet and Child. /// Bullet is aligned vertically with the center of the content's first line /// /// Size that BulletDecorator will assume to position children. protected override Size ArrangeOverride(Size arrangeSize) { UIElement bullet = Bullet; UIElement content = Child; double contentOffsetX = 0; double bulletOffsetY = 0; Size bulletSize = new Size(); // Arrange the bullet if exist if (bullet != null) { bullet.Arrange(new Rect(bullet.DesiredSize)); bulletSize = bullet.RenderSize; contentOffsetX = bulletSize.Width; } // Arrange the content if exist if (content != null) { // Helper arranges child and may substitute a child's explicit properties for its DesiredSize. // The actual size the child takes up is stored in its RenderSize. Size contentSize = arrangeSize; if (bullet != null) { contentSize.Width = Math.Max(content.DesiredSize.Width, arrangeSize.Width - bullet.DesiredSize.Width); contentSize.Height = Math.Max(content.DesiredSize.Height, arrangeSize.Height); } content.Arrange(new Rect(contentOffsetX, 0, contentSize.Width, contentSize.Height)); double centerY = GetFirstLineHeight(content) * 0.5d; bulletOffsetY += Math.Max(0d, centerY - bulletSize.Height * 0.5d); } // Re-Position the bullet if exist if (bullet != null && !DoubleUtil.IsZero(bulletOffsetY)) { bullet.Arrange(new Rect(0, bulletOffsetY, bullet.DesiredSize.Width, bullet.DesiredSize.Height)); } return arrangeSize; } #endregion Protected Methods //------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------- #region Private Methods // This method calculates the height of the first line if the element is TextBlock or FlowDocumentScrollViewer // Otherwise returns the element height private double GetFirstLineHeight(UIElement element) { // We need to find TextBlock/FlowDocumentScrollViewer if it is nested inside ContentPresenter // Common scenario when used in styles is that BulletDecorator content is a ContentPresenter UIElement text = FindText(element); ReadOnlyCollectionlr = null; if (text != null) { TextBlock textElement = ((TextBlock)text); if (textElement.IsLayoutDataValid) lr = textElement.GetLineResults(); } else { text = FindFlowDocumentScrollViewer(element); if (text != null) { TextDocumentView tdv = ((IServiceProvider)text).GetService(typeof(ITextView)) as TextDocumentView; if (tdv != null && tdv.IsValid) { ReadOnlyCollection cr = tdv.Columns; if (cr != null && cr.Count > 0) { ColumnResult columnResult = cr[0]; ReadOnlyCollection pr = columnResult.Paragraphs; if (pr != null && pr.Count > 0) { ContainerParagraphResult cpr = pr[0] as ContainerParagraphResult; if (cpr != null) { TextParagraphResult textParagraphResult = cpr.Paragraphs[0] as TextParagraphResult; if (textParagraphResult != null) { lr = textParagraphResult.Lines; } } } } } } } if (lr != null && lr.Count > 0) { Point ancestorOffset = new Point(); text.TransformToAncestor(element).TryTransform(ancestorOffset, out ancestorOffset); return lr[0].LayoutBox.Height + ancestorOffset.Y * 2d; } return element.RenderSize.Height; } private TextBlock FindText(Visual root) { TextBlock text = root as TextBlock; if (text != null) return text; ContentPresenter cp = root as ContentPresenter; if (cp != null) { if(VisualTreeHelper.GetChildrenCount(cp) == 1) return VisualTreeHelper.GetChild(cp, 0) as TextBlock; } return null; } private FlowDocumentScrollViewer FindFlowDocumentScrollViewer(Visual root) { FlowDocumentScrollViewer text = root as FlowDocumentScrollViewer; if (text != null) return text; ContentPresenter cp = root as ContentPresenter; if (cp != null) { if(VisualTreeHelper.GetChildrenCount(cp) == 1) return VisualTreeHelper.GetChild(cp, 0) as FlowDocumentScrollViewer; } return null; } #endregion //------------------------------------------------------------------- // // Private Memebers // //------------------------------------------------------------------- #region Private Members UIElement _bullet = null; #endregion Private Members } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Component.cs
- GenericUI.cs
- OrderedDictionary.cs
- CompilerGeneratedAttribute.cs
- Annotation.cs
- LoadRetryAsyncResult.cs
- RectangleF.cs
- ConfigurationException.cs
- Accessible.cs
- ParameterToken.cs
- Memoizer.cs
- ListBox.cs
- ParameterCollectionEditorForm.cs
- CursorEditor.cs
- FixedTextPointer.cs
- PropertyEmitter.cs
- peernodestatemanager.cs
- BuildProvider.cs
- XmlReflectionImporter.cs
- ColumnPropertiesGroup.cs
- GifBitmapDecoder.cs
- DataGridViewRowsAddedEventArgs.cs
- RegexRunnerFactory.cs
- Image.cs
- ResourceDescriptionAttribute.cs
- PrintPageEvent.cs
- wgx_render.cs
- AssemblyAttributes.cs
- BrowsableAttribute.cs
- CalendarDay.cs
- SQLGuid.cs
- XPathCompileException.cs
- SpanIndex.cs
- CollectionView.cs
- GetChildSubtree.cs
- DataKeyCollection.cs
- SafeMILHandle.cs
- RuntimeIdentifierPropertyAttribute.cs
- SpotLight.cs
- InputBuffer.cs
- MenuAutomationPeer.cs
- RemotingException.cs
- VirtualizingPanel.cs
- OrderByQueryOptionExpression.cs
- LocalizableAttribute.cs
- CodeLinePragma.cs
- CompilationSection.cs
- DesignTimeVisibleAttribute.cs
- WebPartPersonalization.cs
- SourceLocation.cs
- DesignerLoader.cs
- SqlInternalConnection.cs
- CodeIdentifiers.cs
- DataSourceCache.cs
- SqlWorkflowPersistenceService.cs
- TokenBasedSet.cs
- Blend.cs
- KerberosSecurityTokenProvider.cs
- WhitespaceRule.cs
- PersianCalendar.cs
- StylusPointProperties.cs
- ManualResetEvent.cs
- OperationBehaviorAttribute.cs
- ScopelessEnumAttribute.cs
- TreeNodeMouseHoverEvent.cs
- TogglePattern.cs
- recordstatefactory.cs
- Enum.cs
- WaitHandleCannotBeOpenedException.cs
- FormViewInsertedEventArgs.cs
- PropertyKey.cs
- XpsFilter.cs
- FullTrustAssembly.cs
- UpdatePanelTriggerCollection.cs
- SiteMapProvider.cs
- StickyNoteContentControl.cs
- GenerateScriptTypeAttribute.cs
- XmlReaderSettings.cs
- DiagnosticsConfigurationHandler.cs
- EventHandlerList.cs
- TextSegment.cs
- CompositeControlDesigner.cs
- PrimitiveSchema.cs
- RuntimeResourceSet.cs
- _AcceptOverlappedAsyncResult.cs
- BamlBinaryWriter.cs
- AuthenticationManager.cs
- DllHostedComPlusServiceHost.cs
- Types.cs
- ProtocolsConfigurationEntry.cs
- URLMembershipCondition.cs
- GeometryCollection.cs
- ParameterReplacerVisitor.cs
- MLangCodePageEncoding.cs
- WCFServiceClientProxyGenerator.cs
- SqlBinder.cs
- ContextItem.cs
- ApplyTemplatesAction.cs
- SkipStoryboardToFill.cs
- ProbeDuplexCD1AsyncResult.cs