/// <summary> /// Renders the visual content of the <see cref="ImageFrameRenderer"/>.</summary> /// <param name="context"> /// The <see cref="DrawingContext"/> for the rendering.</param> /// <remarks><para> /// <b>OnRender</b> attempts to draw the shown <see cref="Frame"/> within the <see /// cref="RegularPolygon.Bounds"/> of the current <see cref="Polygon"/>. The drawing is /// centered within the <see cref="ImageFrameRenderer"/>. /// </para><para> /// If drawing fails for any reason, <b>OnRender</b> shows an "invalid" icon instead. /// </para></remarks> protected override void OnRender(DrawingContext context) { base.OnRender(context); // target rectangle centered on viewport Rect target = new Rect( (ActualWidth - Polygon.Bounds.Width) / 2.0, (ActualHeight - Polygon.Bounds.Height) / 2.0, Polygon.Bounds.Width, Polygon.Bounds.Height); // attempt to draw image frame bool success = false; if (Frame != null) { success = ImageUtility.DrawOutlineFrame(context, Brushes.Black, target, Bitmap, Frame.Bounds, Polygon, ScalingX, ScalingY, ColorVector.Empty, PointI.Empty, PointI.Empty); } // draw "invalid" icon on failure if (!success) { ImageUtility.DrawInvalidIcon(context, Brushes.Black, target, Polygon); } }
/// <summary> /// Renders the visual content of the <see cref="ImageStackRenderer"/>.</summary> /// <param name="context"> /// The <see cref="DrawingContext"/> for the rendering.</param> /// <remarks><para> /// <b>OnRender</b> attempts to draw all <see cref="ImageStack"/> elements within the <see /// cref="RegularPolygon.Bounds"/> of the current <see cref="Polygon"/>. The drawing is /// centered within the <see cref="ImageStackRenderer"/>. /// </para><para> /// If drawing fails for any reason, <b>OnRender</b> adds an "invalid" icon on top of /// whatever <see cref="ImageStack"/> elements that are already present.</para></remarks> protected override void OnRender(DrawingContext context) { base.OnRender(context); // target rectangle centered on viewport Rect target = new Rect( (ActualWidth - Polygon.Bounds.Width) / 2.0, (ActualHeight - Polygon.Bounds.Height) / 2.0, Polygon.Bounds.Width, Polygon.Bounds.Height); // draw image stack, or "invalid" icon on failure if (!DrawImageStack(context, target)) { ImageUtility.DrawInvalidIcon(context, Brushes.Black, target, Polygon); } }
/// <summary> /// Renders the visual content of the <see cref="ImageListBoxItem"/>.</summary> /// <param name="context"> /// The <see cref="DrawingContext"/> for the rendering.</param> /// <remarks><para> /// <b>OnRender</b> calls the base class implementation of <see cref="UIElement.OnRender"/>, /// and then attempts to display the current <see cref="ContentControl.Content"/> of the /// <see cref="ImageListBoxItem"/>, depending on its type: /// </para><list type="bullet"><item> /// If the element is an <see cref="EntityImage"/>, its first image frame is drawn above a /// text label showing its identifier. /// </item><item> /// If the element is an <see cref="ImageFrame"/>, the frame is drawn without a label. /// </item><item> /// If the element is a <see cref="RectI"/>, the corresponding region of the <see /// cref="ImageListBox.FrameBitmap"/> is drawn without a label. /// </item></list><para> /// If the element is of any other type, or if an error occurs, the "invalid" icon returned /// by <see cref="Images.Invalid"/> is drawn instead.</para></remarks> protected override void OnRender(DrawingContext context) { base.OnRender(context); // default to base class if not in an ImageListBox ImageListBox listBox = Parent as ImageListBox; if (listBox == null) { return; } // get drawing parameters of containing ImageListBox WriteableBitmap bitmap = listBox.FrameBitmap; ImageScaling scalingX = listBox.ScalingX, scalingY = listBox.ScalingY; // source within bitmap and target within context RectI source = RectI.Empty; Rect target = new Rect(0, 0, ActualWidth, ActualHeight); /* * The default Background brush of a ListBoxItem is transparent, meaning that an item * will not register clicks on anything but the non-transparent image and text label. * * This is very inconvenient, so we always draw a fully opaque background. We use the * ListBox.Background brush for regular items, and the system-defined HighlightBrush * for selected items. The Foreground brush changes automatically as appropriate. * * NOTE: The HighlightBrush must be drawn explicitly anyway, or else the Foreground * of a selected item would be invisible against the Background of the ListBox! */ Brush background = (listBox.SelectedItem == this ? SystemColors.HighlightBrush : listBox.Background); context.DrawRectangle(background, null, target); // check which content we're drawing if (Content is RectI) { source = (RectI)Content; } else { ImageFrame frame = Content as ImageFrame; if (frame == null) { EntityImage image = Content as EntityImage; if (image == null) { goto failure; } // get first image frame and scaling frame = image.Frames[0]; scalingX = image.ScalingX; scalingY = image.ScalingY; // compute bounds of image label Point textLocation = new Point(0, ActualHeight - this._labelHeight); Size textSize = new Size(ActualWidth, this._labelHeight); // reduce image bounds accordingly target.Height -= textSize.Height; // draw text for image label FormattedText text = FormatLabel(image.Id, textSize); context.DrawText(text, textLocation); } // final sanity check for valid image frame if (frame == null || frame.Source.Value == null) { goto failure; } // draw image frame with associated bitmap bitmap = frame.Source.Value.Bitmap; source = frame.Bounds; } // draw specified rectangle with desired bitmap & scaling if (ImageUtility.DrawOutlineFrame(context, Foreground, target, bitmap, source, listBox.Polygon, scalingX, scalingY, ColorVector.Empty, PointI.Empty, PointI.Empty)) { return; } failure: // draw "invalid" icon on failure ImageUtility.DrawInvalidIcon(context, Foreground, target, listBox.Polygon); }