Is there any way to occupy blank space in WrapPanel automatically? - c#

The Children of WrapPanel are populated sequentially like attached screenshot.
Therefore, according to the length of each child, the Panel makes long blank space.
How can I utilize the blank space with re-arrangng the children ?
It seems only few people use WrapPanel so far and no sufficient examples.
Is there some automatic way for this ?
Or do I only need to make own algorithm ?
The WrapPanel plays a very important role to display things but has limited space to display.
Thank you !

Here is a WrapPanel which can optionally rearrange elements using FFDH algorithm, as well as optionally stretch them to remove blank areas (example).
public class StretchyWrapPanel : Panel {
public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register(nameof(ItemWidth), typeof(double),
typeof(StretchyWrapPanel), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => {
((StretchyWrapPanel)o)._itemWidth = (double)e.NewValue;
}));
private double _itemWidth = double.NaN;
[TypeConverter(typeof(LengthConverter))]
public double ItemWidth {
get => _itemWidth;
set => SetValue(ItemWidthProperty, value);
}
public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register(nameof(ItemHeight), typeof(double),
typeof(StretchyWrapPanel), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => {
((StretchyWrapPanel)o)._itemHeight = (double)e.NewValue;
}));
private double _itemHeight = double.NaN;
[TypeConverter(typeof(LengthConverter))]
public double ItemHeight {
get => _itemHeight;
set => SetValue(ItemHeightProperty, value);
}
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(Orientation),
typeof(StretchyWrapPanel), new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsArrange, (o, e) => {
((StretchyWrapPanel)o)._orientation = (Orientation)e.NewValue;
}));
private Orientation _orientation = Orientation.Horizontal;
public Orientation Orientation {
get => _orientation;
set => SetValue(OrientationProperty, value);
}
public static readonly DependencyProperty StretchToFillProperty = DependencyProperty.Register(nameof(StretchToFill), typeof(bool),
typeof(StretchyWrapPanel), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsArrange, (o, e) => {
((StretchyWrapPanel)o)._stretchToFill = (bool)e.NewValue;
}));
private bool _stretchToFill = true;
public bool StretchToFill {
get => _stretchToFill;
set => SetValue(StretchToFillProperty, value);
}
public static readonly DependencyProperty StretchProportionallyProperty = DependencyProperty.Register(nameof(StretchProportionally), typeof(bool),
typeof(StretchyWrapPanel), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsArrange, (o, e) => {
((StretchyWrapPanel)o)._stretchProportionally = (bool)e.NewValue;
}));
private bool _stretchProportionally = true;
public bool StretchProportionally {
get => _stretchProportionally;
set => SetValue(StretchProportionallyProperty, value);
}
public static readonly DependencyProperty RearrangeForBestFitProperty = DependencyProperty.Register(nameof(RearrangeForBestFit), typeof(bool),
typeof(StretchyWrapPanel), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsMeasure, (o, e) => {
((StretchyWrapPanel)o)._rearrangeForBestFit = (bool)e.NewValue;
}));
private bool _rearrangeForBestFit;
public bool RearrangeForBestFit {
get => _rearrangeForBestFit;
set => SetValue(RearrangeForBestFitProperty, value);
}
private struct UVSize {
internal UVSize(Orientation orientation, Size size) {
U = V = 0d;
_isHorizontal = orientation == Orientation.Horizontal;
Width = size.Width;
Height = size.Height;
}
internal UVSize(Orientation orientation, double width, double height) {
U = V = 0d;
_isHorizontal = orientation == Orientation.Horizontal;
Width = width;
Height = height;
}
internal UVSize(Orientation orientation) {
U = V = 0d;
_isHorizontal = orientation == Orientation.Horizontal;
}
internal double U;
internal double V;
private bool _isHorizontal;
internal double Width {
get => _isHorizontal ? U : V;
set {
if (_isHorizontal) {
U = value;
} else {
V = value;
}
}
}
internal double Height {
get => _isHorizontal ? V : U;
set {
if (_isHorizontal) {
V = value;
} else {
U = value;
}
}
}
}
protected override Size MeasureOverride(Size constraint) {
return RearrangeForBestFit ? MeasureBestFit(constraint) : MeasureKeepInOrder(constraint);
}
private Size MeasureKeepInOrder(Size constraint) {
var orientation = Orientation;
var uLimit = new UVSize(orientation, constraint.Width, constraint.Height).U;
var curLineSize = new UVSize(orientation);
var panelSize = new UVSize(orientation);
var itemWidth = ItemWidth;
var itemHeight = ItemHeight;
var itemWidthSet = !double.IsNaN(itemWidth);
var itemHeightSet = !double.IsNaN(itemHeight);
var childConstraint = new Size(
itemWidthSet ? itemWidth : constraint.Width,
itemHeightSet ? itemHeight : constraint.Height);
var children = InternalChildren;
for (int i = 0, count = children.Count; i < count; i++) {
var child = children[i];
if (child == null) continue;
// Flow passes its own constrint to children
child.Measure(childConstraint);
// This is the size of the child in UV space
var sz = new UVSize(orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
if (curLineSize.U + sz.U > uLimit) {
// Need to switch to another line
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V;
curLineSize = sz;
if (sz.U > uLimit) {
// The element is wider then the constrint - give it a separate line
panelSize.U = Math.Max(sz.U, panelSize.U);
panelSize.V += sz.V;
curLineSize = new UVSize(orientation);
}
} else {
// Continue to accumulate a line
curLineSize.U += sz.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
}
}
// The last line size, if any should be added
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V;
// Go from UV space to W/H space
return new Size(panelSize.Width, panelSize.Height);
}
private Size MeasureBestFit(Size constraint) {
var orientation = Orientation;
var uLimit = new UVSize(orientation, constraint.Width, constraint.Height).U;
var itemWidth = ItemWidth;
var itemHeight = ItemHeight;
var itemWidthSet = !double.IsNaN(itemWidth);
var itemHeightSet = !double.IsNaN(itemHeight);
var childConstraint = new Size(
itemWidthSet ? itemWidth : constraint.Width,
itemHeightSet ? itemHeight : constraint.Height);
var children = InternalChildren;
// First-Fit Decreasing Height (FFDH) algorithm
var lines = new List<UVSize>();
for (int i = 0, count = children.Count; i < count; i++) {
var child = children[i];
if (child == null) continue;
// Flow passes its own constrint to children
child.Measure(childConstraint);
// This is the size of the child in UV space
var childSize = new UVSize(orientation,
itemWidthSet ? itemWidth : child.DesiredSize.Width,
itemHeightSet ? itemHeight : child.DesiredSize.Height);
for (var j = 0; j < lines.Count; j++) {
var line = lines[j];
if (line.U + childSize.U <= uLimit) {
lines[j] = new UVSize(orientation) { U = childSize.U, V = Math.Max(childSize.V, line.V) };
goto Next;
}
}
lines.Add(childSize);
Next:
{ }
}
var panelSize = new UVSize(orientation);
for (var i = 0; i < lines.Count; i++) {
var line = lines[i];
panelSize.U = Math.Max(line.U, panelSize.U);
panelSize.V += line.V;
}
// Go from UV space to W/H space
return new Size(panelSize.Width, panelSize.Height);
}
protected override Size ArrangeOverride(Size finalSize) {
return RearrangeForBestFit ? ArrangeBestFit(finalSize) : ArrangeKeepInOrder(finalSize);
}
private static UVSize GetChildSize(Orientation orientation, UIElement child, UVSize fixedChildSize) {
var childSize = new UVSize(orientation, child.DesiredSize);
if (!double.IsNaN(fixedChildSize.U)) childSize.U = fixedChildSize.U;
if (!double.IsNaN(fixedChildSize.V)) childSize.V = fixedChildSize.V;
return childSize;
}
private Size ArrangeKeepInOrder(Size finalSize) {
var orientation = Orientation;
var fixedChildSize = new UVSize(orientation, ItemWidth, ItemHeight);
var children = InternalChildren;
var firstInLine = 0;
var uLimit = new UVSize(orientation, finalSize).U;
var currentLineSize = new UVSize(orientation);
var accumulatedV = 0d;
for (int i = 0, count = children.Count; i < count; i++) {
var child = children[i];
if (child == null) continue;
var childSize = GetChildSize(orientation, child, fixedChildSize);
if (currentLineSize.U + childSize.U > uLimit) {
// Need to switch to another line
if (!double.IsNaN(fixedChildSize.U)) {
ArrangeLineFixedSize(orientation, children, accumulatedV, currentLineSize.V, firstInLine, i, fixedChildSize.U);
} else if (!StretchToFill) {
ArrangeLineDefault(orientation, children, accumulatedV, currentLineSize.V, firstInLine, i);
} else {
ArrangeLineStretch(orientation, children, accumulatedV, currentLineSize.V, firstInLine, i, uLimit, StretchProportionally);
}
accumulatedV += currentLineSize.V;
currentLineSize = childSize;
firstInLine = i;
} else {
// Continue to accumulate a line
currentLineSize.U += childSize.U;
currentLineSize.V = Math.Max(childSize.V, currentLineSize.V);
}
}
// Arrange the last line, if any
if (!double.IsNaN(fixedChildSize.U)) {
ArrangeLineFixedSize(orientation, children, accumulatedV, currentLineSize.V, firstInLine, children.Count, fixedChildSize.U);
} else if (!StretchToFill) {
ArrangeLineDefault(orientation, children, accumulatedV, currentLineSize.V, firstInLine, children.Count);
} else {
ArrangeLineStretch(orientation, children, accumulatedV, currentLineSize.V, firstInLine, children.Count, uLimit, StretchProportionally);
}
return finalSize;
}
private static void ArrangeLineDefault(Orientation orientation, UIElementCollection children, double v, double lineV, int start, int end) {
var position = new UVSize(orientation){ U = 0d, V = v };
for (var i = start; i < end; i++) {
var child = children[i];
if (child != null) {
var childSize = new UVSize(orientation, child.DesiredSize) { V = lineV };
child.Arrange(new Rect(position.Width, position.Height, childSize.Width, childSize.Height));
position.U += childSize.U;
}
}
}
private static void ArrangeLineStretch(Orientation orientation, UIElementCollection children, double v, double lineV, int start, int end,
double limitU, bool stretchProportionally) {
var totalU = 0d;
for (var i = start; i < end; i++) {
totalU += new UVSize(orientation, children[i].DesiredSize).U;
}
var position = new UVSize(orientation) { U = 0d, V = v };
var uExtra = stretchProportionally ? limitU / totalU : (limitU - totalU) / (end - start);
for (var i = start; i < end; i++) {
var child = children[i];
if (child != null) {
var childSize = new UVSize(orientation, child.DesiredSize) { V = lineV };
childSize.U = stretchProportionally ? childSize.U * uExtra : Math.Max(childSize.U + uExtra, 1d);
child.Arrange(new Rect(position.Width, position.Height, childSize.Width, childSize.Height));
position.U += childSize.U;
}
}
}
private static void ArrangeLineFixedSize(Orientation orientation, UIElementCollection children, double v, double lineV, int start, int end, double itemU) {
var position = new UVSize(orientation) { U = 0d, V = v };
var childSize = new UVSize(orientation){ U = itemU, V = lineV };
for (var i = start; i < end; i++) {
var child = children[i];
if (child != null) {
child.Arrange(new Rect(position.Width, position.Height, childSize.Width, childSize.Height));
position.U += childSize.U;
}
}
}
private class ArrangeBestFitLine {
public UVSize Size;
public readonly List<int> ItemIndices = new List<int>();
public void ArrangeDefault(Orientation orientation, UIElementCollection children, double v) {
var position = new UVSize(orientation){ U = 0d, V = v };
for (var i = 0; i < ItemIndices.Count; i++) {
var child = children[ItemIndices[i]];
if (child != null) {
var childSize = new UVSize(orientation, child.DesiredSize) { V = Size.V };
child.Arrange(new Rect(position.Width, position.Height, childSize.Width, childSize.Height));
position.U += childSize.U;
}
}
}
public void ArrangeStretch(Orientation orientation, UIElementCollection children, double v, double limitU, bool stretchProportionally) {
var totalU = 0d;
for (var i = 0; i < ItemIndices.Count; i++) {
totalU += new UVSize(orientation, children[ItemIndices[i]].DesiredSize).U;
}
var position = new UVSize(orientation) { U = 0d, V = v };
var uExtra = stretchProportionally ? limitU / totalU : (limitU - totalU) / ItemIndices.Count;
for (var i = 0; i < ItemIndices.Count; i++) {
var child = children[ItemIndices[i]];
if (child != null) {
var childSize = new UVSize(orientation, child.DesiredSize) { V = Size.V };
childSize.U = stretchProportionally ? childSize.U * uExtra : Math.Max(childSize.U + uExtra, 1d);
child.Arrange(new Rect(position.Width, position.Height, childSize.Width, childSize.Height));
position.U += childSize.U;
}
}
}
public void ArrangeFixedSize(Orientation orientation, UIElementCollection children, double v, double itemU) {
var position = new UVSize(orientation) { U = 0d, V = v };
var childSize = new UVSize(orientation){ U = itemU, V = Size.V };
for (var i = 0; i < ItemIndices.Count; i++) {
var child = children[ItemIndices[i]];
if (child != null) {
child.Arrange(new Rect(position.Width, position.Height, childSize.Width, childSize.Height));
position.U += childSize.U;
}
}
}
}
private Size ArrangeBestFit(Size finalSize) {
var orientation = Orientation;
var fixedChildSize = new UVSize(orientation, ItemWidth, ItemHeight);
var uLimit = new UVSize(orientation, finalSize).U;
// First-Fit Decreasing Height (FFDH) algorithm
var lines = new List<ArrangeBestFitLine>();
var children = InternalChildren;
for (int i = 0, count = children.Count; i < count; i++) {
var child = children[i];
if (child == null) continue;
var childSize = GetChildSize(orientation, child, fixedChildSize);
for (var j = 0; j < lines.Count; j++) {
var line = lines[j];
if (line.Size.U + childSize.U <= uLimit) {
line.Size.U += childSize.U;
line.Size.V = Math.Max(childSize.V, line.Size.V);
line.ItemIndices.Add(i);
goto Next;
}
}
lines.Add(new ArrangeBestFitLine {
Size = childSize,
ItemIndices = { i }
});
Next:
{ }
}
var accumulatedV = 0d;
for (var i = 0; i < lines.Count; i++) {
var line = lines[i];
if (!double.IsNaN(fixedChildSize.U)) {
line.ArrangeFixedSize(orientation, children, accumulatedV, fixedChildSize.U);
} else if (!StretchToFill) {
line.ArrangeDefault(orientation, children, accumulatedV);
} else {
line.ArrangeStretch(orientation, children, accumulatedV, uLimit, StretchProportionally);
}
accumulatedV += line.Size.V;
}
return finalSize;
}
}

Are all your elements in the WrapPanel of the same height? In either case, why not start with a TreeMap control like https://marketplace.visualstudio.com/items?itemName=DevExpress.WPFTreeMapControl and customize it?
EDIT 1 - Based on the comment
It shouldn't be too difficult to implement - I am pretty sure the minimal functionality that you need can be pulled off by inheriting from a panel and hooking the rearrange code in its MeasureOverride and ArrangeOverride methods.
Take a look here too (implements a similar control), could be a good start if you choose to do so: https://codeblitz.wordpress.com/2009/03/20/wpf-auto-arrange-animated-panel/

This simple Panel should do the job:
public class MySpecialWrapPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement child in InternalChildren)
{
child.Measure(availableSize);
}
return new Size();
}
protected override Size ArrangeOverride(Size finalSize)
{
var x = 0d;
var y = 0d;
var height = 0d;
var children = InternalChildren.Cast<UIElement>().ToList();
while (children.Count > 0)
{
var child = children.First();
if (x > 0d && x + child.DesiredSize.Width > finalSize.Width)
{
// try to find child that fits
var fit = children.FirstOrDefault(
c => x + c.DesiredSize.Width <= finalSize.Width);
child = fit ?? child;
if (x + child.DesiredSize.Width > finalSize.Width)
{
x = 0d;
y = height;
}
}
children.Remove(child);
child.Arrange(
new Rect(x, y, child.DesiredSize.Width, child.DesiredSize.Height));
x += child.DesiredSize.Width;
height = Math.Max(height, y + child.DesiredSize.Height);
}
return finalSize;
}
}

You need a custom algorithm for this. I believe the StretchyWrapPanel mentioned here is a good start. After measuring the child items, you can then sort them using custom logic (e.g. bin packing).

Related

Telerik Creating a StackedBarChart

I'm Fairly new to WPF and MVVM in general, I'm trying to follow this tutorial to create a stacked bar chart in telerik/WPF C#:
https://docs.telerik.com/devtools/winforms/knowledge-base/chartview-summary-labels-stacked-bars
But I'm, unsure where to implement the "Custom Renderer and Labels" Code, Can't seem to have it work. Should I declare a seperate class or something? A rough step by step guide is all i need, thanks in advance
this is the example code (I'm not sure where to put it)
public class CustomCartesianRenderer : CartesianRenderer
{
public CustomCartesianRenderer(CartesianArea area)
: base(area)
{ }
protected override void InitializeSeriesLabels()
{
base.InitializeSeriesLabels();
IDictionary<object, List<double?>> summaryValues = new Dictionary<object, List<double?>>();
for (int i = 0; i < this.Area.Series.Count; i++)
{
BarSeries barSeries = this.Area.Series[i] as BarSeries;
if (barSeries == null)
{
continue;
}
for (int j = 0; j < barSeries.DataPoints.Count; j++)
{
CategoricalDataPoint dp = (CategoricalDataPoint)barSeries.DataPoints[j];
if (!summaryValues.ContainsKey(dp.Category))
{
summaryValues.Add(dp.Category, new List<double?>() { dp.Value });
}
else
{
summaryValues[dp.Category].Add(dp.Value);
}
}
}
string lastSeriesName = this.Area.Series[this.Area.Series.Count - 1].Name;
for (int i = 0; i < this.DrawParts.Count; i++)
{
BarLabelElementDrawPart labelPart = this.DrawParts[i] as BarLabelElementDrawPart;
if (labelPart != null && labelPart.Element.Name == lastSeriesName)
{
CustomBarLabelElementDrawPart customLabelPart = new CustomBarLabelElementDrawPart((BarSeries)labelPart.Element, this);
customLabelPart.SummaryValues = summaryValues;
this.DrawParts[i] = customLabelPart;
}
}
}
}
public class CustomBarLabelElementDrawPart : BarLabelElementDrawPart
{
private IDictionary<object, List<double?>> summaryValues;
public CustomBarLabelElementDrawPart(BarSeries series, IChartRenderer renderer)
: base(series, renderer)
{ }
public IDictionary<object, List<double?>> SummaryValues
{
get
{
return this.summaryValues;
}
set
{
this.summaryValues = value;
}
}
public override void Draw()
{
Graphics graphics = this.Renderer.Surface as Graphics;
RadGdiGraphics radGraphics = new RadGdiGraphics(graphics);
foreach (DataPointElement dataPointElement in this.Element.Children)
{
CategoricalDataPoint categoricalDataPoint = dataPointElement.DataPoint as CategoricalDataPoint;
if (!this.summaryValues.ContainsKey(categoricalDataPoint.Category))
{
continue;
}
double? sum = this.summaryValues[categoricalDataPoint.Category].Sum();
string summaryText = string.Format("Sum: {0}", sum);
RadRect slot = categoricalDataPoint.LayoutSlot;
RectangleF barBounds = new RectangleF((float)(this.OffsetX + slot.X), (float)(this.OffsetY + slot.Y), (float)slot.Width, (float)slot.Height);
float realHeight = barBounds.Height * dataPointElement.HeightAspectRatio;
barBounds.Y += barBounds.Height - realHeight;
barBounds.Height = realHeight;
barBounds = this.AdjustBarDataPointBounds(dataPointElement, barBounds);
barBounds.Width = Math.Max(barBounds.Width, 1f);
object state = radGraphics.SaveState();
int horizontalTranslate = (int)(barBounds.X + barBounds.Width / 2);
int verticalTranslate = (int)(barBounds.Y + barBounds.Height / 2);
float angle = (float)this.Element.LabelRotationAngle % 360f;
if (angle != 0)
{
radGraphics.TranslateTransform(horizontalTranslate, verticalTranslate);
radGraphics.RotateTransform(angle);
radGraphics.TranslateTransform(-horizontalTranslate, -verticalTranslate);
}
Size desiredSize = TextRenderer.MeasureText(summaryText, dataPointElement.Font);
FillPrimitiveImpl fill = new FillPrimitiveImpl(dataPointElement, null);
fill.PaintFill(radGraphics, 0, Size.Empty, barBounds);
BorderPrimitiveImpl border = new BorderPrimitiveImpl(dataPointElement, null);
border.PaintBorder(radGraphics, 0, Size.Empty, barBounds);
using (Brush brush = new SolidBrush(dataPointElement.ForeColor))
{
RectangleF drawRectangle = new RectangleF();
drawRectangle.X = barBounds.X + dataPointElement.Padding.Left + (barBounds.Width - desiredSize.Width) /2;
drawRectangle.Y = barBounds.Y + dataPointElement.Padding.Top - desiredSize.Height;
drawRectangle.Width = barBounds.Width - dataPointElement.Padding.Right;
drawRectangle.Height = barBounds.Height - dataPointElement.Padding.Bottom;
StringFormat format = new StringFormat();
graphics.DrawString(summaryText, dataPointElement.Font, brush, drawRectangle, format);
}
if (angle != 0)
{
radGraphics.ResetTransform();
}
radGraphics.RestoreState(state);
}
base.Draw();
}
private RectangleF AdjustBarDataPointBounds(DataPointElement point, RectangleF bounds)
{
RectangleF barBounds = bounds;
if (point.BorderBoxStyle == BorderBoxStyle.SingleBorder || point.BorderBoxStyle == BorderBoxStyle.OuterInnerBorders)
{
barBounds.X += point.BorderWidth - (int)((point.BorderWidth - 1f) / 2f);
barBounds.Width -= point.BorderWidth;
barBounds.Y += point.BorderWidth - (int)((point.BorderWidth - 1f) / 2f);
barBounds.Height -= point.BorderWidth;
}
else if (point.BorderBoxStyle == BorderBoxStyle.FourBorders)
{
barBounds.Y += 1;
barBounds.Height -= 1;
barBounds.X += 1;
barBounds.Width -= 1;
}
if (((CartesianRenderer)this.Renderer).Area.Orientation == System.Windows.Forms.Orientation.Horizontal)
{
barBounds.X--;
}
return barBounds;
}
}

Sending wrong paper size to printer

We have started a project for printing, however we are completely stuck when it comes to telling the printer what paper size is selected.
Everytime we select the paper size and hit print, the printer preview is showing A4 everytime and not our selected size although if we open the print preferences the correct size is selected.
namespace CPrint
{
/// <summary>
/// Логика взаимодействия для ucPrint.xaml
/// </summary>
public partial class ucPrint : UserControl
{
bool SystemChange = false;
double? PaperHeight = null;
double? PaperWidth = null;
public ucPrint()
{
InitializeComponent();
App.Localization.AddControls(this, new string[]
{
"cHeader", "lPrinter", "lCopies","lLayout", "bPrintSettings","lColorManagement","lPrinterProfile", "lPositionSize", "cCenter", "lTop", "lLeft"
});
}
public static BitmapSource ConvertColorProfile(BitmapSource bitmapSource, ColorContext sourceProfile, ColorContext destinationProfile)
{
var bitmapConverted = new ColorConvertedBitmap();
bitmapConverted.BeginInit();
bitmapConverted.Source = bitmapSource;
//bitmapConverted.SourceColorContext = new ColorContext(PixelFormats.Pbgra32);// bitmapSourceFrame.ColorContexts == null ? sourceProfile : bitmapSourceFrame.ColorContexts[0];
bitmapConverted.SourceColorContext = sourceProfile;
bitmapConverted.DestinationColorContext = destinationProfile;
bitmapConverted.DestinationFormat = PixelFormats.Bgra32;
bitmapConverted.EndInit();
return bitmapConverted;
}
private void BPrint_Click(object sender, RoutedEventArgs e)
{
if (cPrinter.SelectedItem == null) { MessageBox.Show("Printer not set"); return; }
if (cPaperSize.SelectedItem == null) { MessageBox.Show("Paper size not set"); return; }
double marging = 30;
if (App.CurrentTemplateControl != null)
{
var img = App.CurrentTemplateControl.GetImage(true);
if (img == null) return;
var image = new Image() { Source = img };
if (cColorProfile != null && cColorProfile.SelectedItem != null && cColorProfile.SelectedIndex > 0)
{
Uri sourceProfileUri = new Uri((cColorProfile.SelectedItem as FileInfo).FullName);
image.Source = ConvertColorProfile(image.Source as BitmapSource, new ColorContext(PixelFormats.Pbgra32), new ColorContext(sourceProfileUri));
}
if (cMirror.IsChecked == true)
{
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(-1, 1, img.Width / 2, img.Height / 2));
image.RenderTransform = transformGroup;
}
PrintDialog printDialog2 = new PrintDialog();
Size size = (Size)(cPaperSize.SelectedItem as ComboBoxItem).DataContext;
printDialog2.PrintQueue = new PrintQueue(new PrintServer(), cPrinter.Text);
//if (printDialog2.ShowDialog() == true)
//{
//Size size = new Size(printDialog2.PrintableAreaWidth, printDialog2.PrintableAreaHeight);
printDialog2.PrintTicket = new PrintTicket()
{
PageMediaSize = new PageMediaSize(size.Width, size.Height)
};
//printDialog2.PrintTicket
Canvas canvas = new Canvas()
{
//Height = PrintContext.ToPx(size.Height),
//Width = PrintContext.ToPx(size.Width),
Height = size.Height,
Width = size.Width,
Background = Brushes.White
};
canvas.Children.Add(image);
double scaleW = (size.Width - marging * 2) / img.Width;
double scaleH = (size.Height - marging * 2) / img.Height;
if (scaleW < 1 || scaleH < 1)
{
Canvas.SetLeft(image, marging);
Canvas.SetTop(image, marging);
double scale = scaleW > scaleH ? scaleH : scaleW;
var transformGroup = new TransformGroup();
transformGroup.Children.Add(new ScaleTransform(scale, scale, 0, 0));
image.RenderTransform = transformGroup;
}
else if (cCenter.IsChecked == true)
{
Canvas.SetLeft(image, size.Width / 2 - img.Width / 2);
Canvas.SetTop(image, size.Height / 2 - img.Height / 2);
}
else
{
Canvas.SetLeft(image, marging);
Canvas.SetTop(image, marging);
}
printDialog2.PrintVisual(canvas, "Print");
//}
}
return;
}
private void CPrinter_DropDownOpened(object sender, EventArgs e)
{
SystemChange = true;
var lastPrinterName = cPrinter.Text;
cPrinter.Items.Clear();
int index = -1;
cPrinter.SelectedIndex = index;
foreach (string strPrinter in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
index++;
cPrinter.Items.Add(strPrinter);
if (strPrinter == lastPrinterName)
cPrinter.SelectedIndex = index;
}
SystemChange = false;
}
private void CPrinter_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0 && SystemChange == false)
{
var printer = new System.Drawing.Printing.PrinterSettings();
printer.PrinterName = e.AddedItems[0].ToString();
var lastPaperName = cPaperSize.Text;
cPaperSize.Items.Clear();
int index = -1;
cPaperSize.SelectedIndex = index;
foreach (System.Drawing.Printing.PaperSize paper in printer.PaperSizes)
{
index++;
cPaperSize.Items.Add(new ComboBoxItem() { Content = paper.PaperName, DataContext = new Size(paper.Width, paper.Height) });
if (paper.PaperName == lastPaperName)
cPaperSize.SelectedIndex = index;
}
Properties.Settings.Default.DefaultDirectPrinter = printer.PrinterName;
Properties.Settings.Default.Save();
}
}
private void CPaperSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
{
Properties.Settings.Default.DefaultDirectPaper = ((ComboBoxItem)e.AddedItems[0]).Content.ToString();
Properties.Settings.Default.Save();
}
}
public void UpdateControls()
{
SystemChange = true;
if (!String.IsNullOrWhiteSpace(Properties.Settings.Default.DefaultDirectPrinter))
{
SystemChange = true;
var lastPrinterName = cPrinter.Text;
cPrinter.Items.Clear();
int index = -1;
cPrinter.SelectedIndex = index;
foreach (string strPrinter in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
index++;
cPrinter.Items.Add(strPrinter);
if (strPrinter == Properties.Settings.Default.DefaultDirectPrinter)
cPrinter.SelectedIndex = index;
}
SystemChange = false;
if (!String.IsNullOrWhiteSpace(Properties.Settings.Default.DefaultDirectPaper))
{
var printer = new System.Drawing.Printing.PrinterSettings();
printer.PrinterName = Properties.Settings.Default.DefaultDirectPrinter;
string lastPaperName = Properties.Settings.Default.DefaultDirectPaper;
cPaperSize.Items.Clear();
int indexP = -1;
cPaperSize.SelectedIndex = indexP;
foreach (System.Drawing.Printing.PaperSize paper in printer.PaperSizes)
{
indexP++;
cPaperSize.Items.Add(new ComboBoxItem() { Content = paper.PaperName, DataContext = new Size(paper.Width, paper.Height) });
if (paper.PaperName == lastPaperName)
cPaperSize.SelectedIndex = indexP;
}
}
}
if (!String.IsNullOrWhiteSpace(Properties.Settings.Default.DefaultDirectColorProfile))
{
var lastValue = Properties.Settings.Default.DefaultDirectColorProfile;
cColorProfile.Items.Clear();
int index = -1;
cColorProfile.SelectedIndex = index;
cColorProfile.Items.Add("");
index++;
foreach (var file in App.Icc.items)
{
index++;
cColorProfile.Items.Add(file);
if (file.FullName == lastValue)
cColorProfile.SelectedIndex = index;
}
}
SystemChange = false;
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
}
private void CColorProfile_DropDownOpened(object sender, EventArgs e)
{
var lastValue = cColorProfile.Text;
cColorProfile.Items.Clear();
int index = -1;
cColorProfile.SelectedIndex = index;
cColorProfile.Items.Add("");
index++;
foreach (var file in App.Icc.items)
{
index++;
cColorProfile.Items.Add(file);
if (file.Name == lastValue)
cColorProfile.SelectedIndex = index;
}
}
private void CColorProfile_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!SystemChange)
{
Properties.Settings.Default.DefaultDirectColorProfile = (cColorProfile.SelectedItem as FileInfo)?.FullName;
Properties.Settings.Default.Save();
}
}
}
}
I expect if we select A5, it tells the print driver to print A5,
If we select a custom "user defined" paper size, it tells the printer which size is selected. And not fixing this at A4 everytime
We cant seem to set the paper size outside the print dialog.
I believe; following this and this MSDN article; you are going to want to do something along the lines of:
System.Drawing.Printing.PaperSize paperSize = new System.Drawing.Printing.PaperSize("custom", width, height);
PrintDocument printDoc = new PrintDocument();
printDoc.DefaultPageSettings.PaperSize = paperSize;
I have walk through your code,
I think some event raise by front end (XAML) on specific use cases that is the overriding the actual value in "Properties.Settings.Default."
It would be better to resolve if you provide a XAML code for this issue.
I can look into it and will give you better solution.
You can share me code here is my skype : shsakariya

Current LOD level - LOD Group Unity

I'm having trouble leading with LOD Group, because I want to know which is the current active LOD level that I see in the screen. I only can access to the percentage with
GameObject.GetComponent<LODGroup>().GetLODs()[size].screenRelativeTransitionHeight;
Someone knows how to solve this? Thanks in advance.
Searching through the answers answers.unity3d.com, I came to this:
http://answers.unity3d.com/questions/684467/find-the-lod-step-which-is-currently-used.html
LODGroup lodGroup = obj.GetComponent<LODGroup>();
if (lodGroup != null)
{
Transform lodTransform = lodGroup.transform;
foreach (Transform child in lodTransform)
{
var renderer = child.GetComponent<Renderer> ();
if (renderer != null && renderer.isVisible)
{
Debug.Log("This LODlevel is used: " + child.name);
}
}
}
You can find out which LOD level is currently active by looking into the names of children GameObjects Renderers which are currently visible (visible on the screen).
I had the same issue, and finally found out a solution that really works. (The renderer.isVisible is not updated often enough to be reliable, unfortunately, and I did not want to add additionnal components on ever LOD subobjects.)
I uploaded the solution here: https://github.com/JulienHeijmans/EditorScripts/blob/master/Scripts/Utility/Editor/LODExtendedUtility.cs
It is mostly code that I took from here: https://github.com/Unity-Technologies/AutoLOD/blob/master/Scripts/Extensions/LODGroupExtensions.cs I just rmeoved what was not necessary, and addod other utility functions that I had to use often.
It has been made to be used as an in-editor utility script, but the math to get the currently visible LOD level is there.
private static int GetLODCurShowLevel(Camera cam, LODGroup lodGroup)
{
//var inv_SceneViewCamHeight = 1.0f / (cam.pixelHeight - 6.0f);
var inv_SceneViewCamHeight = 1.0f / (cam.pixelHeight);
var lods = lodGroup.GetLODs();
for (int lodIDX = 0; lodIDX < lods.Length; lodIDX++)
{
var lod = lods[lodIDX];
var renderers = lod.renderers;
for (int renderIDX = 0; renderIDX < renderers.Length; renderIDX++)
{
var renderer = renderers[renderIDX];
// method1:
//var heightInScreen = Mathf.Abs(cam.WorldToScreenPoint(renderer.bounds.max).y - cam.WorldToScreenPoint(renderer.bounds.min).y);
// method2:
var heightInScreen = GetHeightInScreen(cam, renderer);
var ratioInScren = heightInScreen * inv_SceneViewCamHeight;
if (ratioInScren > lod.screenRelativeTransitionHeight)
{
return lodIDX;
}
}
}
return -1;
}
private static float GetHeightInScreen(Camera cam, Renderer renderer)
{
var min = renderer.bounds.min;
var max = renderer.bounds.max;
// F = Front
var FTL = new Vector3(min.x, max.y, min.z);
var FTR = new Vector3(max.x, max.y, min.z);
var FBR = new Vector3(max.x, min.y, min.z);
var FBL = new Vector3(min.x, min.y, min.z);
// Back
var BTL = new Vector3(min.x, max.y, max.z);
var BTR = new Vector3(max.x, max.y, max.z);
var BBR = new Vector3(max.x, min.y, max.z);
var BBL = new Vector3(min.x, min.y, max.z);
// to screen space pos
FTL = cam.WorldToScreenPoint(FTL);
FTR = cam.WorldToScreenPoint(FTR);
FBR = cam.WorldToScreenPoint(FBR);
FBL = cam.WorldToScreenPoint(FBL);
BTL = cam.WorldToScreenPoint(BTL);
BTR = cam.WorldToScreenPoint(BTR);
BBR = cam.WorldToScreenPoint(BBR);
BBL = cam.WorldToScreenPoint(BBL);
var maxY = FTL.y;
maxY = Mathf.Max(FTR.y, maxY);
maxY = Mathf.Max(FBR.y, maxY);
maxY = Mathf.Max(FBL.y, maxY);
maxY = Mathf.Max(BTL.y, maxY);
maxY = Mathf.Max(BTR.y, maxY);
maxY = Mathf.Max(BBR.y, maxY);
maxY = Mathf.Max(BBL.y, maxY);
var minY = FTL.y;
minY = Mathf.Min(FTR.y, minY);
minY = Mathf.Min(FBR.y, minY);
minY = Mathf.Min(FBL.y, minY);
minY = Mathf.Min(BTL.y, minY);
minY = Mathf.Min(BTR.y, minY);
minY = Mathf.Min(BBR.y, minY);
minY = Mathf.Min(BBL.y, minY);
return maxY - minY;
}
public class TestingStoreLODGroupCurLODLevel : MonoBehaviour
{
public bool[] lodVisibleArr;
public int GetCurLOD()
{
if (lodVisibleArr != null)
{
var len = lodVisibleArr.Length;
for (int i = 0; i < len; i++)
{
if (lodVisibleArr[i])
{
return i;
}
}
}
return -1;
}
}
public class TestingCheckVisibleChanged : MonoBehaviour
{
public int belongLOD;
public TestingStoreLODGroupCurLODLevel storeLOD;
private void OnBecameInvisible()
{
if (storeLOD)
{
storeLOD.lodVisibleArr[belongLOD] = false;
}
}
private void OnBecameVisible()
{
if (storeLOD)
{
storeLOD.lodVisibleArr[belongLOD] = true;
}
}
}
private void SetupCheckLODInfo(GameObject go)
{
var lodGroup = go.GetComponent<LODGroup>();
if (lodGroup == null)
{
return;
}
var storeLODComp = go.GetComponent<TestingStoreLODGroupCurLODLevel>();
if (storeLODComp != null)
{
return;
}
storeLODComp = go.AddComponent<TestingStoreLODGroupCurLODLevel>();
var lods = lodGroup.GetLODs();
for (int lodIDX = 0; lodIDX < lods.Length; lodIDX++)
{
var lod = lods[lodIDX];
var renderers = lod.renderers;
for (int rendererIDX = 0; rendererIDX < renderers.Length; rendererIDX++)
{
var renderer = renderers[rendererIDX];
var checkVisibleComp = renderer.gameObject.GetComponent<TestingCheckVisibleChanged>();
if (checkVisibleComp == null)
{
checkVisibleComp = renderer.gameObject.AddComponent<TestingCheckVisibleChanged>();
}
checkVisibleComp.belongLOD = lodIDX;
checkVisibleComp.storeLOD = storeLODComp;
}
}
storeLODComp.lodVisibleArr = new bool[lods.Length];
}
private void UnSetupCheckLODInfo(GameObject go)
{
var lodGroup = go.GetComponent<LODGroup>();
if (lodGroup == null)
{
return;
}
var storeLODComp = go.GetComponent<TestingStoreLODGroupCurLODLevel>();
if (storeLODComp != null)
{
GameObject.Destroy(storeLODComp);
}
var lods = lodGroup.GetLODs();
for (int lodIDX = 0; lodIDX < lods.Length; lodIDX++)
{
var lod = lods[lodIDX];
var renderers = lod.renderers;
for (int rendererIDX = 0; rendererIDX < renderers.Length; rendererIDX++)
{
var renderer = renderers[rendererIDX];
var checkVisibleComp = renderer.gameObject.GetComponent<TestingCheckVisibleChanged>();
if (checkVisibleComp != null)
{
GameObject.Destroy(checkVisibleComp);
}
}
}
}

How to select or highlight the text on mouse move event in WritableBitmap in wpf c#

I have WritableBitmap image and I have set in image control src. I am creating rectangle when user move on the selected text area.I am also using PDFtron SDK to get selected text from the PDF document.
we are getting WritableBitmap image from PDF. We have to select text on line wise.
I am using this code to draw the screen:
System.Drawing.Rectangle rectangle = new System.Drawing.Rectangle((int)Math.Min(_downX, x),
(int)Math.Min(_downY, y),
(int)Math.Abs(_downX - x),
(int)Math.Abs(_downY - y));
System.Drawing.Bitmap myBitmap = new System.Drawing.Bitmap(#"D:\PDF\ScreenDraw\WpfApplication1\WpfApplication1\Image\Capture.PNG");
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(myBitmap))
{
System.Drawing.Color customColor = System.Drawing.Color.FromArgb(50, System.Drawing.Color.Red);
System.Drawing.SolidBrush shadowBrush = new System.Drawing.SolidBrush(customColor);
g.FillRectangles(shadowBrush, new System.Drawing.Rectangle[] { rectangle });
}
//myBitmap.Save(#"D:\PDF\abc.png");
//bitmapSource = new BitmapImage(new Uri(#"D:\PDF\abc.png", UriKind.Absolute));
using (var memory = new System.IO.MemoryStream())
{
myBitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
memory.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
Img.Source = bitmapImage;
}
How can I select the text with line wise not a Rect wise?
I have to select text as shown in the above image.
What you want is impossible. You have a bitmap and it is not magically aware of the text in it and nothing will change that.
Although it's not that there is nothing you can do about it.
I don't have time to provide complete solution, but I can provide step-by-step instruction how to achieve the best possible solution.
What you can do is:
Text dimensions definition - Create control with grid overlaid on the image with editable X- and Y-axis step and offset. Then you will be able to calibrate the grid with the lines of text (Y). And character width (X).
Something like that should do (I think you will get the general idea):
public int XGridStep
{
get { return (int)base.GetValue(XGridStepProperty); }
set
{
base.SetValue(XGridStepProperty, value);
RepaintGrid();
}
}
public static readonly DependencyProperty XGridStepProperty = DependencyProperty.Register("XGridStepProperty", typeof(int), typeof(PlanLayout), new PropertyMetadata(100));
public int XGridOffset
{
get { return (int)base.GetValue(XGridOffsetProperty); }
set
{
base.SetValue(XGridOffsetProperty, value);
RepaintGrid();
}
}
public static readonly DependencyProperty XGridOffsetProperty = DependencyProperty.Register("XGridOffsetProperty", typeof(int), typeof(PlanLayout), new PropertyMetadata(0));
public bool XGridVisible
{
get { return (bool)base.GetValue(XGridVisibleProperty); }
set
{
base.SetValue(XGridVisibleProperty, value);
RepaintGrid();
}
}
public static readonly DependencyProperty XGridVisibleProperty = DependencyProperty.Register("XGridVisibleProperty", typeof(bool), typeof(PlanLayout), new PropertyMetadata(false));
public int YGridStep
{
get { return (int)base.GetValue(YGridStepProperty); }
set
{
base.SetValue(YGridStepProperty, value);
RepaintGrid();
}
}
public static readonly DependencyProperty YGridStepProperty = DependencyProperty.Register("YGridStepProperty", typeof(int), typeof(PlanLayout), new PropertyMetadata(100));
public int YGridOffset
{
get { return (int)base.GetValue(YGridOffsetProperty); }
set
{
base.SetValue(YGridOffsetProperty, value);
RepaintGrid();
}
}
public static readonly DependencyProperty YGridOffsetProperty = DependencyProperty.Register("YGridOffsetProperty", typeof(int), typeof(PlanLayout), new PropertyMetadata(0));
public bool YGridVisible
{
get { return (bool)base.GetValue(YGridVisibleProperty); }
set
{
base.SetValue(YGridVisibleProperty, value);
RepaintGrid();
}
}
public static readonly DependencyProperty YGridVisibleProperty = DependencyProperty.Register("YGridVisibleProperty", typeof(bool), typeof(PlanLayout), new PropertyMetadata(false));
private void RepaintGrid()
{
if (!IsEditable)
return;
foreach (Line l in _gridXLines)
content.Children.Remove(l);
_gridXLines.Clear();
if (XGridVisible)
for (int i = XGridOffset; i < content.ActualWidth; i += XGridStep)
{
Line line = new Line();
line.IsHitTestVisible = false;
line.Stroke = Brushes.Black;
line.Y1 = 0;
line.Y2 = content.ActualHeight;
line.X1 = line.X2 = i;
if (Math.Abs(line.X1 - content.ActualWidth) < XGridStep * 0.5 || line.X1 < XGridStep * 0.5)
continue;
_gridXLines.Add(line);
content.Children.Add(line);
Canvas.SetZIndex(line, 0);
}
foreach (Line l in _gridYLines)
content.Children.Remove(l);
_gridYLines.Clear();
if (YGridVisible)
for (int i = YGridOffset; i < content.ActualHeight; i += YGridStep)
{
Line line = new Line();
line.IsHitTestVisible = false;
line.Stroke = Brushes.Black;
line.X1 = 0;
line.X2 = content.ActualWidth;
line.Y1 = line.Y2 = i;
if (Math.Abs(line.Y1 - content.ActualHeight) < YGridStep * 0.5 || line.Y1 < YGridStep * 0.5)
continue;
_gridYLines.Add(line);
content.Children.Add(line);
Canvas.SetZIndex(line, 0);
}
}
Text selection - All you have to do now is add "Snap to grid" ability to your control. Again, just for reference:
private void elementWrapper_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (_mouseHandlingMode != MouseHandlingMode.Dragging)
return;
SelectableElement element = (SelectableElement)sender;
Point curContentPoint = e.GetPosition(content);
//Vector elementDragVector = curContentPoint - _origContentMouseDownPoint;
_origContentMouseDownPoint = curContentPoint;
//double destinationLeft = Canvas.GetLeft(element) + elementDragVector.X;
//double destinationTop = Canvas.GetTop(element) + elementDragVector.Y;
double destinationLeft = curContentPoint.X - element.ActualWidth / 2;
double destinationTop = curContentPoint.Y - element.ActualHeight / 2;
if (SnapToGrid)
{
if (XGridVisible)
{
foreach (Line l in _gridXLines)
l.StrokeThickness = 1;
Line nearest = GetNearestXGridLine((int)curContentPoint.X);
if (Math.Abs(curContentPoint.X - nearest.X1) < XGridStep * 0.2)
{
destinationLeft = nearest.X1 - element.ActualWidth / 2;
nearest.StrokeThickness = 3;
}
}
if (YGridVisible)
{
foreach (Line l in _gridYLines)
l.StrokeThickness = 1;
Line nearest = GetNearestYGridLine((int)curContentPoint.Y);
if (Math.Abs(curContentPoint.Y - nearest.Y1) < YGridStep * 0.2)
{
destinationTop = nearest.Y1 - element.ActualHeight / 2;
nearest.StrokeThickness = 3;
}
}
}
if (destinationLeft < 0)
destinationLeft = 0;
if (destinationLeft > content.ActualWidth - element.ActualWidth)
destinationLeft = content.ActualWidth - element.ActualWidth;
if (destinationTop < 0)
destinationTop = 0;
if (destinationTop > content.ActualHeight - element.ActualHeight)
destinationTop = content.ActualHeight - element.ActualHeight;
Canvas.SetLeft(element, destinationLeft);
Canvas.SetTop(element, destinationTop);
element.ElementContent.Position.X = curContentPoint.X;
element.ElementContent.Position.Y = curContentPoint.Y;
e.Handled = true;
}
private Line GetNearestXGridLine(int xpos)
{
return _gridXLines.OrderBy(gl => Math.Abs((int)gl.X1 - xpos)).First();
}
private Line GetNearestYGridLine(int Ypos)
{
return _gridYLines.OrderBy(gl => Math.Abs((int)gl.Y1 - Ypos)).First();
}
Graphical representation of the selection - Now draw (up to) 3 rectangles: from topleft point of the selection to bottomright point of the relevant text line, topleft point of the next line to bottomright point of the line before the last selected and topleft point of the last line to bottomright of selection
Get text - Get partial text data from these rectangles and join.

namespace doesn't exist

I would like to try out a code in Microsoft Visual C# Express Edition and I'm getting this error:
The type or namespace name 'Properties' does not exist in the namespace 'EducationalSuite.Core' (are you missing an assembly reference?)
I right click the Reference but I didn't find the "Properties" either the "EducationalSuite.Core".
Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Media;
using System.Resources;
namespace EducationalSuite.Core.Plugins
{
public delegate void RectangleItemClickedDelegate(Rectangle rect, int index);
public partial class GeoSafariItem : Control
{
protected List<Rectangle> lastFlashingItems = new List<Rectangle>();
protected int lastHeight = 0;
private Image imageFile = null;
protected List<Rectangle> hotspots = new List<Rectangle>();
protected Dictionary<int, string> textItems = new Dictionary<int, string>();
protected Dictionary<int, FileInfo> audioItems = new Dictionary<int, FileInfo>();
protected Rectangle lastRectangle;
protected int selectedIndex = 0;
protected int countItemsLeft = 6;
protected int countItemsRight = 6;
protected int imageOffsetTop = 0;
protected int imageOffsetBottom = 0;
protected bool paintHotSpots = false, colorSwitch = false, paintItemLabels = false;
protected Timer timer = new Timer();
public event RectangleItemClickedDelegate HotspotClick;
public event RectangleItemClickedDelegate QuestionItemClick;
public event RectangleItemClickedDelegate QuestionItemRightClick;
protected void OnHotspotClick(Rectangle rect, int index)
{
if (HotspotClick != null)
{
HotspotClick(this.RectangleToScreen(rect), index);
}
}
protected void OnQuestionItemRightClick(Rectangle rect, int index)
{
if (QuestionItemRightClick != null)
{
QuestionItemRightClick(this.RectangleToScreen(rect), index);
}
}
protected void OnQuestionItemClick(Rectangle rect, int index)
{
if (QuestionItemClick != null)
{
QuestionItemClick(this.RectangleToScreen(rect), index);
}
}
public GeoSafariItem()
{
this.imageFile = EducationalSuite.Core.Properties.Resources.singlepixel;
timer.Interval = 100;
timer.Tick += new EventHandler(timer_Tick);
timer.Enabled = true;
this.MouseUp += new MouseEventHandler(GeoSafariItem_MouseUp);
// Activates double buffering
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
this.DoubleBuffered = true;
//InitializeComponent();
}
public void SetItemText(int index, string text)
{
if (string.IsNullOrEmpty(text))
{
if (this.textItems.ContainsKey(index)) textItems.Remove(index);
}
else
{
this.textItems[index] = text;
}
if (PaintItemLabels)
{
this.Invalidate();
}
}
public string GetItemText(int index)
{
if (this.textItems.ContainsKey(index))
{
return this.textItems[index];
}
else
{
return string.Empty;
}
}
public void SetItemAudio(int index, FileInfo file)
{
if ((file == null) && !file.Exists)
{
if (this.audioItems.ContainsKey(index)) audioItems.Remove(index);
}
else
{
this.audioItems[index] = file;
}
}
public FileInfo GetItemAudio(int index)
{
if (this.audioItems.ContainsKey(index))
{
return this.audioItems[index];
}
else
{
return null;
}
}
#region Recording Regions
bool isRecording = false;
int recordingIndex = 0;
Point recordTopLeft = Point.Empty;
Point recordBottomRight = Point.Empty;
List<Rectangle> recordedRectangles = new List<Rectangle>();
public void StartRecording()
{
isRecording = true;
recordingIndex = 0;
selectedIndex = 0;
recordedRectangles.Clear();
this.MouseUp += new MouseEventHandler(GeoSafariItemRecord_MouseUp);
this.Invalidate();
}
public List<Rectangle> FinishRecording()
{
isRecording = false;
this.MouseUp -= new MouseEventHandler(GeoSafariItemRecord_MouseUp);
this.Invalidate();
this.Hotspots.Clear();
foreach (Rectangle r in recordedRectangles)
{
this.Hotspots.Add(r);
}
return recordedRectangles;
}
private void GeoSafariItemRecord_MouseUp(object sender, MouseEventArgs e)
{
if (isRecording)
{
Rectangle size = SizeRect;
double ratio = (double)imageFile.Height / (double)size.Height;
if (recordTopLeft == Point.Empty)
{
recordTopLeft = new Point(
(int)(((double)e.Location.X - (double)size.Left) * ratio),
(int)(((double)e.Location.Y - (double)size.Top) * ratio)
);
}
else
{
recordBottomRight = new Point(
(int)(((double)e.Location.X - (double)size.Left) * ratio),
(int)(((double)e.Location.Y - (double)size.Top) * ratio)
);
Rectangle r = new Rectangle(recordTopLeft,
new Size(recordBottomRight.X - recordTopLeft.X, recordBottomRight.Y - recordTopLeft.Y));
this.recordedRectangles.Add(r);
recordingIndex++;
selectedIndex++;
recordTopLeft = Point.Empty;
recordBottomRight = Point.Empty;
}
}
this.Invalidate();
}
#endregion
void timer_Tick(object sender, EventArgs e)
{
colorSwitch = !colorSwitch;
if (lastRectangle.Width > 0)
{
this.Invalidate(lastRectangle);
}
else
{
this.Invalidate();
}
}
private Rectangle SizeRect
{
get
{
int rw, rh,
cw = (this.Width - 42),
ch = (this.Height - 2),
ox = 21,
oy = 1;
rw = cw;
rh = ch;
double imageRatio = (double)imageFile.Width / (double)imageFile.Height;
double controlRatio = (double)cw / (double)ch;
if (controlRatio > imageRatio)
{
rw = (int)Math.Round((double)rh * imageRatio);
ox += Math.Abs(rw - cw) / 2;
}
else if (controlRatio < imageRatio)
{
rh = (int)Math.Round((double)rw / imageRatio);
oy += Math.Abs(rh - ch) / 2;
}
return new Rectangle(ox, oy, rw, rh);
}
}
void GeoSafariItem_MouseUp(object sender, MouseEventArgs e)
{
Rectangle size = SizeRect;
for (int i = 0; i < hotspots.Count; i++)
{
Rectangle hotspot = hotspots[i];
double ratio = (double)size.Height / (double)imageFile.Height;
Rectangle adjustedRectange = new Rectangle(
size.Left + (int)(hotspot.X * ratio),
size.Top + (int)(hotspot.Y * ratio),
(int)(hotspot.Width * ratio),
(int)(hotspot.Height * ratio));
if (adjustedRectange.Contains(e.Location))
{
OnHotspotClick(hotspot, i);
return;
}
}
for (int i = 0; i < lastFlashingItems.Count; i++)
{
if (lastFlashingItems[i].Contains(e.Location))
{
if (e.Button == MouseButtons.Right)
OnQuestionItemRightClick(lastFlashingItems[i], i);
else
OnQuestionItemClick(lastFlashingItems[i], i);
return;
}
}
}
public List<Rectangle> Hotspots
{
get { return hotspots; }
}
public Image ImageFile
{
get { return imageFile; }
set
{
imageFile = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int SelectedIndex
{
get { return selectedIndex; }
set { selectedIndex = value; this.Invalidate(); }
}
public int CountItemsLeft
{
get { return countItemsLeft; }
set
{
countItemsLeft = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int CountItemsRight
{
get { return countItemsRight; }
set
{
countItemsRight = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int ImageOffsetTop
{
get { return imageOffsetTop; }
set
{
imageOffsetTop = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public int ImageOffsetBottom
{
get { return imageOffsetBottom; }
set
{
imageOffsetBottom = value;
lastFlashingItems.Clear();
this.Invalidate();
}
}
public bool PaintHotSpots
{
get { return paintHotSpots; }
set { paintHotSpots = value; this.Invalidate(); }
}
public bool PaintItemLabels
{
get { return paintItemLabels; }
set { paintItemLabels = value; this.Invalidate(); }
}
protected override void OnPaint(PaintEventArgs pe)
{
Graphics g = pe.Graphics;
string itemText;
SizeF sizeItemText;
double topOffset = imageOffsetTop;
double bottomOffset = imageOffsetBottom;
double topOffsetPct = (double)topOffset / (double)imageFile.Height;
double bottomOffsetPct = (double)bottomOffset / (double)imageFile.Height;
Rectangle size = SizeRect;
SolidBrush brush = new SolidBrush(this.BackColor);
g.FillRectangle(brush, 0, 0, this.Width - 1, this.Height - 1);
g.FillRectangle(Brushes.Ivory, size.X - 25, size.Y, size.Width + 50, size.Height);
g.DrawRectangle(Pens.DarkKhaki, size.X - 25, size.Y - 1, size.Width + 50, size.Height + 1);
g.DrawImage(imageFile, size.X, size.Y, size.Width, size.Height);
Rectangle rect, rectItemText;
Brush selectedColor = (colorSwitch ? Brushes.Crimson : Brushes.Red);
topOffset = topOffsetPct * size.Height;
bottomOffset = bottomOffsetPct * size.Height;
int tmpHeight = (size.Height - (int)topOffset - (int)bottomOffset) / countItemsLeft;
if (size.Height != this.lastHeight || this.lastFlashingItems.Count == 0)
{
lastHeight = size.Height;
lastFlashingItems.Clear();
int actualIndex = 0;
for (int i = 0; i < countItemsLeft; i++)
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
int xx = size.X - 18;
rect = new Rectangle(xx, yy, 16, 8);
this.lastFlashingItems.Add(rect);
g.FillRectangle((actualIndex == selectedIndex ? selectedColor : Brushes.Khaki), rect);
g.DrawRectangle(Pens.DarkKhaki, rect);
if (actualIndex == selectedIndex)
{
lastRectangle = rect;
}
itemText = this.GetItemText(actualIndex);
if (PaintItemLabels && !string.IsNullOrEmpty(itemText))
{
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + 10;
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
tmpHeight = (size.Height - (int)topOffset - (int)bottomOffset) / countItemsRight;
for (int i = 0; i < countItemsRight; i++)
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
int xx = size.X + size.Width + 2;
rect = new Rectangle(xx, yy, 16, 8);
this.lastFlashingItems.Add(rect);
g.FillRectangle((actualIndex == selectedIndex ? selectedColor : Brushes.Khaki), rect);
g.DrawRectangle(Pens.DarkKhaki, rect);
if (actualIndex == selectedIndex)
{
lastRectangle = rect;
}
itemText = this.GetItemText(actualIndex);
if (PaintItemLabels && !string.IsNullOrEmpty(itemText))
{
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + size.Width - 10 - Convert.ToInt32(sizeItemText.Width);
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
}
else
{
lastHeight = size.Height;
for (int i = 0; i < lastFlashingItems.Count; i++)
{
g.FillRectangle((i == selectedIndex ? selectedColor : Brushes.Khaki), lastFlashingItems[i]);
g.DrawRectangle(Pens.DarkKhaki, lastFlashingItems[i]);
if (i == selectedIndex)
{
lastRectangle = lastFlashingItems[i];
}
}
if (PaintItemLabels)
{
int actualIndex = 0;
for (int i = 0; i < countItemsLeft; i++)
{
itemText = this.GetItemText(actualIndex);
if (!string.IsNullOrEmpty(itemText))
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + 10;
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
tmpHeight = (size.Height - (int)topOffset - (int)bottomOffset) / countItemsRight;
for (int i = 0; i < countItemsRight; i++)
{
itemText = this.GetItemText(actualIndex);
if (!string.IsNullOrEmpty(itemText))
{
int yy = size.Y + (tmpHeight * i) + (int)topOffset;
// Draw Text next to each notch
sizeItemText = g.MeasureString(itemText, this.Font);
int xxx = size.X + size.Width - 10 - Convert.ToInt32(sizeItemText.Width);
rectItemText = new Rectangle(xxx, yy, Convert.ToInt32(sizeItemText.Width), Convert.ToInt32(sizeItemText.Height));
PaintHotspot(g, Color.White, rectItemText, 200);
g.DrawString(itemText, this.Font, Brushes.Black, (float)xxx, (float)yy);
}
actualIndex++;
}
}
}
// Calling the base class OnPaint
base.OnPaint(pe);
if (this.isRecording)
{
for (int i = 0; i < this.recordedRectangles.Count; i++)
{
rect = recordedRectangles[i];
double ratio = (double)size.Height / (double)imageFile.Height;
Rectangle adjustedRectange = new Rectangle(
size.Left + (int)(rect.X * ratio),
size.Top + (int)(rect.Y * ratio),
(int)(rect.Width * ratio),
(int)(rect.Height * ratio));
PaintHotspot(g, Color.LightBlue, adjustedRectange, (i + 1).ToString());
}
}
else if (this.paintHotSpots)
{
for (int i = 0; i < hotspots.Count; i++)
{
Rectangle hotspot = hotspots[i];
double ratio = (double)size.Height / (double)imageFile.Height;
Rectangle adjustedRectange = new Rectangle(
size.Left + (int)(hotspot.X * ratio),
size.Top + (int)(hotspot.Y * ratio),
(int)(hotspot.Width * ratio),
(int)(hotspot.Height * ratio));
PaintHotspot(g, Color.LightGreen, adjustedRectange, (i + 1).ToString());
}
}
}
protected virtual void PaintHotspot(Graphics g, Color c, Rectangle hotspot, int alpha)
{
PaintHotspot(g, c, hotspot, alpha, null);
}
protected virtual void PaintHotspot(Graphics g, Color c, Rectangle hotspot, string txt)
{
PaintHotspot(g, c, hotspot, 100, txt);
}
protected virtual void PaintHotspot(Graphics g, Color c, Rectangle hotspot, int alpha, string txt)
{
SolidBrush brush = new SolidBrush(Color.FromArgb(alpha, c));
g.FillRectangle(brush, hotspot);
if (!string.IsNullOrEmpty(txt))
g.DrawString(txt, this.Font, Brushes.DarkGreen, hotspot.Location);
}
}
}
Update
I imagine the following line is causing the error.
this.imageFile = EducationalSuite.Core.Properties.Resources.singlepixel;
The code is referring to a image resource "singlepixel". This image must be in the default resource file of the EducationalSuite.Core assembly. First confirm that you are currently editing the said assembly by opening Project Properties and checking the Default Namespace on the Application page. This should state "EducationalSuite.Core". If this isn't the case, you are most likely missing a reference to the said assembly.
If you have the EducationalSuite.Core project open the easiest way to add the singlepixel resource is to open project properties, Resources tab and creating a new default resource file. From the top open the Add Resource drop down and select existing file or new image depending on whether you have the file already or if you need to create it. Name the resource "singlepixel".
Visual Studio will generate Resources helper class under Properties namespace for you so you can access the resource through the Properties.Resources.singlepixel under EducationalSuite.Core in your code.
Old answer
In general Properties namespace is the namespace which contains application or user specific settings. You can add these settings (and the namespace) by navigating to the Settings tab in the Properties of the project.
Unfortunately it's kind of hard to say more based on this information. Could you provide the piece of code that causes this error?
If you double click the error message the IDE will take you to the line which is causing the error.
Most likely the piece of code is expecting a setting variable which is not added to the project.
Looks like you are missing the Reference. If it is not under References in solution explorer than I would do a file search in windows for "EducationalSuite.Core" to see where it is on the system and add it. You may also be missing the "using" statement? If you hover over the "Properties" text you should get a small drop down that will add the using's for you.
If this does not help, more information would be helpful?
Hope this helps!

Categories

Resources