/// <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> /// Draws the <see cref="ImageStack"/> to the specified rectangle.</summary> /// <param name="context"> /// The <see cref="DrawingContext"/> for the drawing.</param> /// <param name="target"> /// The drawing region within <paramref name="context"/>, in device-independent pixels. /// </param> /// <returns> /// <c>true</c> if all <see cref="ImageStack"/> elements were drawn without errors; /// otherwise, <c>false</c>.</returns> /// <remarks> /// <b>DrawImageStack</b> draws the selected <see cref="Frames"/> of all <see /// cref="ImageStack"/> elements to the specified <paramref name="target"/> rectangle within /// the specified <paramref name="context"/>.</remarks> private bool DrawImageStack(DrawingContext context, Rect target) { Debug.Assert(ImageStack.Count == Frames.Count); // fail if no images are available if (ImageStack.Count == 0) { return(false); } // draw selected frames of all images for (int i = 0; i < ImageStack.Count; i++) { ImageStackEntry entry = ImageStack[i]; // quit on first unavailable image EntityImage image = entry.Image.Value; if (image == null) { return(false); } // determine selected frame int frameIndex = Frames[i] % image.Frames.Count; ImageFrame frame = image.Frames[frameIndex]; // quit on first unavailable bitmap if (frame.Source.Value == null) { return(false); } // get desired image scaling, unless disabled ImageScaling scalingX = ImageScaling.None, scalingY = ImageScaling.None; if (!entry.UseUnscaled) { scalingX = image.ScalingX; scalingY = image.ScalingY; } // draw frame with specified display parameters if (!ImageUtility.DrawOutlineFrame(context, Brushes.Black, target, frame.Source.Value.Bitmap, frame.Bounds, Polygon, scalingX, scalingY, entry.ColorShift, entry.Offset, entry.ScalingVector)) { return(false); } } return(true); }
/// <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); }