Related
I am making a software to help me at work. It reads two excel (xlsx) files and get some info from them. Then it put the info in one of the two datagridviews or in both datagridviews.
Then i have a number that i need to show when i print the datagridviews. In print preview all is exactly as i want but when printing on paper it removes (or doesn't remember) everything about first datagridview and anything i print with it and start from the 2nd datagridview.
Here how it shows in print preview:
but when i print it on paper i get like this
Why the first datagridview gone on paper but if i print it PDF from Microsoft print to PDF i get PDF that has exactly as the preview.
Problem only when printing on paper.
Here is my printing code https://pastebin.com/6ZF2FevZ
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Printing;
using System.Drawing.Text;
using System.Linq;
using System.Windows.Forms;
namespace Motabaka
{
class DGVsPrinter
{
private Font fontD;
private Brush brushD = Brushes.Black;
private bool dgv1Finished;
private string a3800, a1800;
public string Title { get; set; }
public bool IncludeDateAndTimeInFooter { get; set; }
public bool IncludePageNumberInFooter { get; set; }
public bool IncludeEndingPhraseAtTheEnd { get; set; }
public string EndingPhrase { get; set; } = "End";
private DataGridView dataGridView1, dataGridView2;
private int rowIndex;
private int cellCount;
private int pageNumber = 1;
private readonly PrintDocument printDoc;
private int iTotalWidth1;
private int iTotalWidth2;
private Dictionary<int, int> ColumntWidths;
private Dictionary<int, int> arrColumnWidths1 = new Dictionary<int, int>();
private Dictionary<int, int> arrColumnWidths2 = new Dictionary<int, int>();
private bool preview;
public DGVsPrinter(DataGridView dataGridView1, DataGridView dataGridView2, PrintDocument printDoc, string A3800, string A1800)
{
this.dataGridView1 = dataGridView1;
this.dataGridView2 = dataGridView2;
this.printDoc = printDoc;
fontD = new Font(dataGridView1.Font, FontStyle.Bold);
printDoc.BeginPrint += OnBeginPrint;
printDoc.PrintPage += OnPrintPage;
a3800 = A3800;
a1800 = A1800;
}
public void Print(bool preview = false)
{
this.preview = preview;
rowIndex = 0;
cellCount = 0;
pageNumber = 0;
var dgvs = new DataGridView[] { dataGridView1, dataGridView2 };
foreach (DataGridView dgv in dgvs)
{
var rows = dgv.Rows
.Cast<DataGridViewRow>()
.FirstOrDefault(r => !r.IsNewRow && r.Visible);
if (rows != null)
cellCount = rows.Cells
.Cast<DataGridViewCell>()
.Where(c => c.Visible)
.Count();
if (cellCount == 0)
{
//MessageBox.Show(new Form() { FormBorderStyle = FormBorderStyle.None }, "Nothing to print...");
continue;
}
}
if (cellCount == 0)
{
MessageBox.Show(new Form() { FormBorderStyle = FormBorderStyle.None }, "Nothing to print...");
return;
}
if (preview)
{
try
{
using (var pd = new PrintPreviewDialog())
{
pd.Document = printDoc;
pd.ShowDialog();
}
}
catch (Exception ex)
{
Error.Log(ex);
}
}
else
{
try
{
using (var pd = new PrintDialog())
{
pd.Document = printDoc;
if (pd.ShowDialog() == DialogResult.OK)
{
pd.Document.Print();
}
}
}
catch (Exception ex)
{
Error.Log(ex);
}
}
}
private void OnBeginPrint(object sender, PrintEventArgs e)
{
try
{
rowIndex = 0; pageNumber = 1;
iTotalWidth1 = 0;
iTotalWidth2 = 0;
arrColumnWidths1.Clear();
arrColumnWidths2.Clear();
foreach (DataGridViewColumn dgvGridCol in dataGridView1.Columns)
{
if (!dgvGridCol.Visible) { continue; }
iTotalWidth1 += dgvGridCol.Width;
}
foreach (DataGridViewColumn dgvGridCol in dataGridView2.Columns)
{
if (!dgvGridCol.Visible) { continue; }
iTotalWidth2 += dgvGridCol.Width;
}
}
catch (Exception ex)
{
Error.Log(ex, "Error while printing [OnBeginPrint]");
}
}
private void OnPrintPage(object sender, PrintPageEventArgs e)
{
try
{
e.Graphics.Clear(Color.White);
var w = e.MarginBounds.Width / cellCount;
var x = e.MarginBounds.X;
var y = e.MarginBounds.Y;
int h;
Rectangle rec;
while (true)
{
var dgv = !dgv1Finished ? dataGridView1 : dataGridView2;
ColumntWidths = (dgv == dataGridView1) ? arrColumnWidths1 : arrColumnWidths2;
var totalWidths = (dgv == dataGridView1) ? iTotalWidth1 : iTotalWidth2;
var iTmpWidth = 0;
if (pageNumber == 1)
{
for (int i = dgv.Columns.Count - 1; i >= 0; i--)
{
DataGridViewColumn GridCol = dgv.Columns[i];
if (!GridCol.Visible) continue;
iTmpWidth = (int)(Math.Floor(GridCol.Width /
(double)totalWidths * totalWidths *
(e.MarginBounds.Width / (double)totalWidths)));
if (!ColumntWidths.Keys.Contains(GridCol.Index))
{
ColumntWidths.Add(GridCol.Index, iTmpWidth);
}
}
}
using (var sf = new StringFormat())
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
sf.Trimming = StringTrimming.None;
e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
// Uncomment to print the headers in the first page only.
//if (pageNumber == 1)
//{
h = dgv.RowTemplate.Height + 20;
#region Title
var TextToDraw = dgv.Tag?.ToString();
var xCenter = e.MarginBounds.Left + e.MarginBounds.Width / 2;
e.Graphics.DrawString(TextToDraw, fontD, brushD, xCenter, y - 20, sf);
#endregion
using (var strf = new StringFormat())
{
strf.Alignment = StringAlignment.Far;
strf.LineAlignment = StringAlignment.Near;
#region Amount
var amount = (dgv == dataGridView1) ? a1800 : a3800;
var XC = e.MarginBounds.Right;
var font = new Font(dgv.Font.FontFamily, 12f, FontStyle.Regular);
e.Graphics.DrawString(amount, font, brushD, XC, y - 20, strf);
#endregion
}
for (int i = dgv.Columns.Count - 1; i >= 0; i--)
{
var col = dgv.Columns[i];
if (col.Visible)
{
w = ColumntWidths[col.Index];
rec = new Rectangle(x, y, w, h);
e.Graphics.FillRectangle(Brushes.AliceBlue, rec);
e.Graphics.DrawString(
col.HeaderText,
col.DataGridView.Font,
Brushes.Black,
rec,
sf);
//Pen pen = new Pen(Color.Black, 1.3f);
//pen.Alignment = PenAlignment.Inset;
//e.Graphics.DrawRectangle(pen, rec);
Color[] colors;
if (false)
{
colors = new Color[]
{
SystemColors.ControlDark,
SystemColors.ControlDarkDark,
SystemColors.ControlLightLight,
SystemColors.ControlLight
};
}
else
{
colors = new Color[]
{
SystemColors.ControlLightLight,
SystemColors.ControlLight,
SystemColors.ControlDark,
SystemColors.ControlDarkDark
};
}
using (Pen p = new Pen(colors[0]))
{
e.Graphics.DrawLine(p, rec.X, rec.Bottom - 1,
rec.X, rec.Y);
e.Graphics.DrawLine(p, rec.X, rec.Y,
rec.Right - 1, rec.Y);
}
using (Pen p = new Pen(colors[1]))
{
e.Graphics.DrawLine(p, rec.X + 1, rec.Bottom - 2,
rec.X + 1, rec.Y + 1);
e.Graphics.DrawLine(p, rec.X + 1, rec.Y + 1,
rec.Right - 2, rec.Y + 1);
}
using (Pen p = new Pen(colors[2]))
{
e.Graphics.DrawLine(p, rec.X, rec.Bottom - 1,
rec.Right - 1, rec.Bottom - 1);
e.Graphics.DrawLine(p, rec.Right - 1, rec.Bottom - 1,
rec.Right - 1, rec.Y);
}
using (Pen p = new Pen(colors[3]))
{
e.Graphics.DrawLine(p, rec.X + 1, rec.Bottom - 2,
rec.Right - 2, rec.Bottom - 2);
e.Graphics.DrawLine(p, rec.Right - 2, rec.Bottom - 2,
rec.Right - 2, rec.Y + 1);
}
x += w;
}
}
x = e.MarginBounds.X;
y += h;
//}
/*Drawing the rows with their content*/
for (var i = rowIndex; i < dgv.RowCount; i++)
{
var row = dgv.Rows[i];
if (!row.Visible) continue;
if (row.IsNewRow) break;
h = GetRowHeight(e.Graphics, row, e.MarginBounds, sf);
if (h > e.MarginBounds.Height)
{
MessageBox.Show("Insufficient height.");
e.Cancel = true;
return;
}
/*Drawing row's cells with their content*/
for (int r = row.Cells.Count - 1; r >= 0; r--)
{
var cell = row.Cells[r];
if (!cell.Visible) { continue; }
w = ColumntWidths[cell.ColumnIndex];
rec = new Rectangle(x, y, w, h);
if (rec.Bottom > e.MarginBounds.Bottom)
{
pageNumber++;
rowIndex = i;
e.HasMorePages = true;
return;
}
var color = (cell.InheritedStyle.BackColor == Color.Yellow) ? new SolidBrush(SystemColors.Window) : new SolidBrush(cell.InheritedStyle.BackColor);
e.Graphics.FillRectangle(color, rec);
e.Graphics.DrawString(
cell.FormattedValue.ToString(),
dgv.Font,
Brushes.Black,
rec,
sf);
e.Graphics.DrawRectangle(Pens.Black, rec);
x += rec.Width;
}/*Done drawing the cells in a row*/
x = e.MarginBounds.X;
y += h;
}/*Done drawing all the rows*/
#region Date and time
if (IncludeDateAndTimeInFooter)
{
var strDate = DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToShortTimeString();
var wdate = e.Graphics.MeasureString(strDate, fontD, e.MarginBounds.Height, sf).Width;
var hdate = e.Graphics.MeasureString(strDate, fontD, e.MarginBounds.Height, sf).Height;
var yBottom = e.MarginBounds.Height + e.MarginBounds.Top;
var recDate = new Rectangle(e.MarginBounds.X, yBottom, e.MarginBounds.Width, (int)hdate);
//e.Graphics.FillRectangle(Brushes.LightSkyBlue, recDate);
e.Graphics.DrawRectangle(Pens.Black, recDate);
e.Graphics.DrawString(strDate, fontD, brushD, recDate.X, yBottom);
}
#endregion
#region Page Number
if (IncludePageNumberInFooter)
{
var pNumber = "Page " + pageNumber;
var yBottom = e.MarginBounds.Height + e.MarginBounds.Top;
var xRight = e.MarginBounds.Left + (e.MarginBounds.Width - e.Graphics.MeasureString(pNumber, fontD, e.MarginBounds.Width, sf).Width);
e.Graphics.DrawString(pNumber, fontD, brushD, xRight, yBottom);
}
#endregion
y = y + 70;
rowIndex = 0;
dgv1Finished = true;
e.HasMorePages = (dgv == dataGridView1);
}
if (!e.HasMorePages)
{
if (IncludeEndingPhraseAtTheEnd)
{
using (var strf = new StringFormat())
{
strf.LineAlignment = StringAlignment.Center;
strf.Alignment = StringAlignment.Center;
strf.FormatFlags = StringFormatFlags.DirectionRightToLeft;
var fontD = new Font(dgv.Font, FontStyle.Bold);
var brushD = Brushes.Black;
var xCenter = e.MarginBounds.Left + e.MarginBounds.Width / 2;
var yBottom = e.MarginBounds.Top
+ e.MarginBounds.Height
+ e.Graphics.MeasureString(EndingPhrase, fontD, e.MarginBounds.Height, strf).Height;
e.Graphics.DrawString(EndingPhrase, fontD, brushD, xCenter, y - 60, strf);
}
}
break;
}
}
}
catch (Exception ex)
{
Error.Log(ex, " Error while printing [OnPrintPage]");
}
}
private int GetRowHeight(
Graphics g,
DataGridViewRow row,
Rectangle bounds,
StringFormat sf,
int minHeight = 22)
{
var cells = row.Cells.OfType<DataGridViewTextBoxCell>()
.Where(c => c.Visible);
if (cells == null) return minHeight;
/*(longest, next) => next.Length > longest.Length ? next : longest*/
var cell = cells.Aggregate((DataGridViewTextBoxCell)null, (x, y) => (x != null) && (!string.IsNullOrWhiteSpace(x.FormattedValue.ToString()) && !string.IsNullOrWhiteSpace(y.FormattedValue.ToString())) &&
(x.FormattedValue.ToString().Length > y.FormattedValue.ToString().Length) ? x : y);
if (cell == null) return minHeight;
var h = g.MeasureString(cell.FormattedValue.ToString(),
row.DataGridView.Font,
new SizeF(ColumntWidths[cell.ColumnIndex], bounds.Height),
sf).ToSize().Height;
return Math.Max(h + 10, minHeight); // 6 for top and bottom margins...
}
}
}
I call the print like this
var print = new DGVsPrinter(dataGridView1, dataGridView2, printDocument1, Final3800L.Text, Final1800L.Text)
{
IncludeDateAndTimeInFooter = true,
IncludePageNumberInFooter = true
};
print.Print(true);
I found the problem.
If i print it by print dialog it prints good. But when i show the preview, this problem happens. Because i didn't set dgv1Finished to false on OnBeginPrint.
when it actually prints It runs the code again and dgv1Finished is already true after the preview so it get datagridview2 first and nothing about datagridvie1.
I only have to set dgv1Finished = false in OnBeginPrint and now it prints everything.
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).
I am trying to cluster(group) every circle that's uninterrupted overlapping (connected) to each other how could I do that? (preferably in a pretty efficient way).
(I have messed around trying to write some recursive functions but haven't gotten anything to work.)
I have created a VS project to visualize the problem.
Download here:
Generates Random circles.
How the clustering currently works:
(its only looks at what circle is overlapping that specific circle not all that is connected)
How it should look if its working
(separate clusters for all connecting circles)
CODE: (C#)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// Cluster overlapping circles
// Patrik Fröhler
// www.patan77.com
// 2017-08-14
namespace circleGroup
{
struct circle // the circle "object"
{
public float[] pos;
public int radius;
public Color color;
public int id;
public float x
{
get { return pos[0]; }
set { pos[0] = value; }
}
public float y
{
get { return pos[1]; }
set { pos[1] = value; }
}
}
public partial class Form1 : Form
{
DB _DB = new DB(); // "Global Database"
public Form1()
{
InitializeComponent();
}
private static circle createCircle(float _x = 0, float _y = 0, int _radius = 1, Color? _color = null, int _id = -1) // creates a circle
{
circle tmpCircle = new circle() { pos = new float[2], x = _x, y = _y, radius = _radius, id = _id };
tmpCircle.color = _color ?? Color.Black;
return (tmpCircle);
}
private circle[] genRngCircles(int _n) // generates an array of random circles
{
Random rng = new Random();
circle tmpC;
circle[] tmpCarr = new circle[_n];
for (int i = 0; i < _n; i++)
{
tmpC = createCircle();
tmpC.radius = rng.Next(10, 75);
tmpC.x = rng.Next(tmpC.radius, (512 - tmpC.radius));
tmpC.y = rng.Next(tmpC.radius, (512 - tmpC.radius));
tmpC.color = Color.FromArgb(127, rng.Next(0, 255), rng.Next(0, 255), rng.Next(0, 255));
tmpC.id = i;
tmpCarr[i] = tmpC;
}
return tmpCarr;
}
private void drawCircle(circle _circle, Graphics _g) // draws one circle
{
SolidBrush sb = new SolidBrush(_circle.color);
_g.FillEllipse(sb, (_circle.x - _circle.radius), (_circle.y - _circle.radius), (_circle.radius * 2), (_circle.radius * 2));
sb.Dispose();
}
private void drawString(float[] _pos, string _text, Graphics _g) // draws text
{
StringFormat sf = new StringFormat();
sf.LineAlignment = StringAlignment.Center;
sf.Alignment = StringAlignment.Center;
Font font = new Font("Arial", 12);
SolidBrush sb = new SolidBrush(Color.Black);
float x = _pos[0];
float y = _pos[1];
_g.DrawString(_text, font, sb, x, y, sf);
font.Dispose();
sb.Dispose();
}
private void drawCircleArr(circle[] _circleArr, Graphics _g)// draws an array of circles
{
_g.Clear(panel1.BackColor);
for (int i = 0; i < _circleArr.Length; i++)
{
drawCircle(_circleArr[i], _g);
drawString(_circleArr[i].pos, _circleArr[i].id.ToString(), _g);
}
}
static double mDistance<T>(T[] _p0, T[] _p1) // gets euclidean distance between two points of arbitrary numbers of dimensions
{
double[] p0 = new double[] { Convert.ToDouble(_p0[0]), Convert.ToDouble(_p0[1]) };
double[] p1 = new double[] { Convert.ToDouble(_p1[0]), Convert.ToDouble(_p1[1]) };
double tmp = 0;
double tmpTotal = 0;
for (int i = 0; i < _p0.Length; i++)
{
tmp = (p0[i] - p1[i]);
tmpTotal += (tmp * tmp);
}
double output = Math.Sqrt(tmpTotal);
return (output);
}
private bool overlap(circle _c0, circle _c1) // checks if two circles overlap
{
double dis = mDistance(_c0.pos, _c1.pos);
if (dis <= (_c0.radius + _c1.radius))
{
return (true);
}
return (false);
}
private Color avgColor(List<circle> _colorArr) // averages mutiple colors togehter
{
float ia = 0;
float ir = 0;
float ig = 0;
float ib = 0;
for (int i = 0; i < _colorArr.Count; i++)
{
ia += _colorArr[i].color.A;
ir += _colorArr[i].color.R;
ig += _colorArr[i].color.G;
ib += _colorArr[i].color.B;
}
byte a = Convert.ToByte(Math.Round(ia / _colorArr.Count));
byte r = Convert.ToByte(Math.Round(ir / _colorArr.Count));
byte g = Convert.ToByte(Math.Round(ig / _colorArr.Count));
byte b = Convert.ToByte(Math.Round(ib / _colorArr.Count));
return (Color.FromArgb(a, r, g, b));
}
private void treeView(List<circle>[] _circleLArr) // Create Treeview
{
treeView1.Nodes.Clear();
for (int i = 0; i < _circleLArr.Length; i++)
{
treeView1.Nodes.Add(i.ToString());
for (int j = 0; j < _circleLArr[i].Count; j++)
{
treeView1.Nodes[i].Nodes.Add(_circleLArr[i][j].id.ToString());
}
}
treeView1.ExpandAll();
}
private void drawCircleClusters(List<circle>[] _circleLArr, Graphics _g) // draws the circle clusters
{
_g.Clear(panel1.BackColor);
circle tmpC;
Color tmpColor;
for (int i = 0; i < _circleLArr.Length; i++)
{
tmpColor = avgColor(_circleLArr[i]);
for (int j = 0; j < _circleLArr[i].Count; j++)
{
tmpC = _circleLArr[i][j];
tmpC.color = tmpColor;
drawCircle(tmpC, _g);
drawString(_circleLArr[i][j].pos, _circleLArr[i][j].id.ToString(), _g);
}
}
}
//----------------------------------------------------
private List<circle>[] simpleOverlap(circle[] _circleArr) // test what circles overlaps
{
List<circle>[] tmpLArr = new List<circle>[_circleArr.Length];
for (int i = 0; i < (_circleArr.Length); i++)
{
tmpLArr[i] = new List<circle>();
for (int j = 0; j < (_circleArr.Length); j++)
{
if (overlap(_circleArr[i], _circleArr[j]))
{
tmpLArr[i].Add(_circleArr[j]);
}
}
}
return (tmpLArr);
}
/*
private circle[] recurOverlap(circle[] _circleArr) // recursive overlap test(not done/working)
{
List<circle> overlapArr = new List<circle>();
List<circle> dontOverlapArr = new List<circle>();
bool loop = true;
int n = 0;
while (loop)
{
if (overlap(_circleArr[0], _circleArr[n]))
{
overlapArr.Add(_circleArr[n]);
dontOverlapArr.Insert(0, _circleArr[n]);
circle[] dontArr = dontOverlapArr.ToArray();
recurOverlap(dontArr);
}
else
{
dontOverlapArr.Add(_circleArr[n]);
}
n++;
if (n >= _circleArr.Length)
{
loop = false;
}
}
if(_circleArr.Length <= 1)
{
return _circleArr;
}
else{
return overlapArr.ToArray();
}
}
private List<circle>[] clusterBrecur(circle[] _circleArr)
{
List<circle>[] tmpLArr = new List<circle>[_circleArr.Length];
for (int i = 0; i < (_circleArr.Length); i++)
{
tmpLArr[i] = new List<circle>();
recurOverlap(_circleArr);
}
return (tmpLArr);
}*/
private void run() // Run function
{
treeView1.Nodes.Clear(); // clear tree view
_DB.g = panel1.CreateGraphics();// Create Panel Graphics to draw on
_DB.circleArr = genRngCircles(10); // Creates an array with random circles
drawCircleArr(_DB.circleArr, _DB.g); // Draws the random circles
clusterAbtn.Enabled = true; // enables the cluster button
}
private void clusterA() // clusterA function
{
_DB.circleClusters = simpleOverlap(_DB.circleArr); // runs cluster algorithm test A
treeView(_DB.circleClusters); // Creates the treeview
drawCircleClusters(_DB.circleClusters, _DB.g); // draws the circle clusters
}
private void clusterB()
{
}
private void clusterA_rClick()
{
drawCircleArr(_DB.circleArr, _DB.g); // Draws the random circles
}
private void runBtn_Click(object sender, EventArgs e) // run button click
{
run();
}
private void clusterAbtn_MouseUp(object sender, MouseEventArgs e)
{
switch (e.Button)
{
case MouseButtons.Left:
clusterA();
break;
case MouseButtons.Right:
clusterA_rClick();
break;
}
}
private void clusterBbtn_Click(object sender, EventArgs e) // clusterB button click
{
clusterB();
}
}
class DB // "Database"
{
public Graphics g;
public circle[] circleArr;
public List<circle>[] circleClusters;
}
}
The current "overlap function"
private List<circle>[] simpleOverlap(circle[] _circleArr) // test what circles overlaps
{
List<circle>[] tmpLArr = new List<circle>[_circleArr.Length];
for (int i = 0; i < (_circleArr.Length); i++)
{
tmpLArr[i] = new List<circle>();
for (int j = 0; j < (_circleArr.Length); j++)
{
if (overlap(_circleArr[i], _circleArr[j]))
{
tmpLArr[i].Add(_circleArr[j]);
}
}
}
return (tmpLArr);
}
I made following change to your code. Looks like working
private List<circle>[] simpleOverlap(circle[] _circleArr) // test what circles overlaps
{
List<List<circle>> list = new List<List<circle>>();
//List<circle>[] tmpLArr = new List<circle>[_circleArr.Length];
//for (int i = 0; i < (_circleArr.Length); i++)
foreach (circle circle in _circleArr)
{
List<circle> cluster = null;
//tmpLArr[i] = new List<circle>();
//for (int j = 0; j < (_circleArr.Length); j++)
//{
// if (overlap(_circleArr[i], _circleArr[j]))
// {
// tmpLArr[i].Add(_circleArr[j]);
// }
//}
foreach(List<circle> cluster2 in list)
{
foreach (circle circle2 in cluster2)
{
if (overlap(circle, circle2))
{
cluster = cluster2;
goto label_001;
}
}
}
label_001:
if (cluster == null)
{
cluster = new List<circle>();
list.Add(cluster);
}
cluster.Add(circle);
}
bool flag = true;
for (int i = 0; i < list.Count; i += (flag ? 1 : 0))
{
flag = true;
List<circle> cluster = list[i];
for (int j = i + 1; j < list.Count; j++)
{
List<circle> cluster2 = list[j];
if (Intersects(cluster, cluster2))
{
cluster.AddRange(cluster2);
list.Remove(cluster2);
j--;
flag = false;
}
}
}
return list.ToArray();
//return (tmpLArr);
}
bool Intersects(List<circle> cluster1, List<circle> cluster2)
{
foreach (circle circle1 in cluster1)
{
foreach (circle circle2 in cluster2)
{
if (overlap(circle1, circle2))
{
return true;
}
}
}
return false;
}
I had to add 1 more method bool Intersects(List<circle> cluster1, List<circle> cluster2). See if it helps.
I believe the function you are looking for is intersection. I have attached an article by Mike K which I believe will give you an idea of how to approach this in your own code.
C# circles intersections
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);
}
}
}
}
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!