Set text width component via script - c#

I am instantiating the leader board on the image (https://imgur.com/a/I0aVSaR), the problem is, I can't align properly the numbers on the center row.
I think that if I set the width of the numbers of the right row, the center row will be aligned. Right now the elements on the right row have different widths.
My problem now is how to set the width via script, I already tried rectransform.deltaSize, SetSizeWithCurrentAnchors and other similar things with no luck.
I've also tried to set a preferred width on the inspector on Layout Element but is ignored (https://imgur.com/a/O3hDeGN).
This is how the elements are created:
for (int i = 0; i < leaderboardEntries.Count; i++)
{
Transform newEntry = Instantiate(entryPrefab);
newEntry.SetParent(leaderboardEntriesPanel);
Text entryName = newEntry.GetChild(0).GetComponent<Text>();
Text entryScore = newEntry.GetChild(1).GetComponent<Text>();
Text entryRank = newEntry.GetChild(2).GetComponent<Text>();
entryName.text = leaderboardEntries[i].getName();
entryScore.text = leaderboardEntries[i].getScore().ToString();
entryRank.text = (i+1).ToString();
entryName.alignment = TextAnchor.UpperLeft;
entryScore.alignment = TextAnchor.UpperRight;
entryRank.alignment = TextAnchor.UpperRight;
}
The center row is the score, the left row the Name and the right row the rank.
Thanks!

if you want to change the width and height of a RectTransform you can try this:
rectTransform.sizeDelta = new Vector2( width, height);
but fixing their alignment need something else, first of all, all alignments should be same, UpperLeft or MiddleLeft for example.
then set anchor point of all your entries to the same value also.
then something like this should work properly:
// in this example I considered all anchor points are middle left and all
// alignments are middle left too
float width = leaderboardEntriesPanel.GetComponent<RectTransform>().rect.width;
for (int i = 0; i < leaderboardEntries.Count; i++)
{
Transform newEntry = Instantiate(entryPrefab);
newEntry.SetParent(leaderboardEntriesPanel);
Text entryName = newEntry.GetChild(0).GetComponent<Text>();
Text entryScore = newEntry.GetChild(1).GetComponent<Text>();
Text entryRank = newEntry.GetChild(2).GetComponent<Text>();
entryName.text = leaderboardEntries[i].getName();
entryScore.text = leaderboardEntries[i].getScore().ToString();
entryRank.text = (i+1).ToString();
entryName.GetComponent<RectTransform>().anchoredPosition = new Vector2(width / 15, entryName.GetComponent<RectTransform>().anchoredPosition.y);
entryScore.GetComponent<RectTransform>().anchoredPosition = new Vector2(width / 2, entryScore.GetComponent<RectTransform>().anchoredPosition.y);
entryRank.GetComponent<RectTransform>().anchoredPosition = new Vector2(width * 4 / 5, entryRank.GetComponent<RectTransform>().anchoredPosition.y);
}

Related

draw picture box and get coordinates

i'm newbie here and also in c#.
my project is to create a box in grid view.
then when click desired box, i'll get the box coordinate or position and box will change the colour.
when click another box, the previous box colour will change to original.
the box will resize when total size for rows x cols more than panel2 size.
i wanna extend the function of code by add new button NEXT, when click, then next picture box will be highlight and also coordinate will update. how to relate new button with existing picture box?
for (int cols = 0; cols < COLUMNS; cols++)
{
for (int rows = 0; rows < ROWS; rows++)
{
PictureBox newPic = new PictureBox();
newPic.Height = HEIGHT;
newPic.Width = WIDTH;
newPic.BackColor = Color.Maroon;
int x = cols * (HEIGHT + SPACE);
int y = rows * (WIDTH + SPACE);
newPic.Location = new Point(x + SPACE, y + SPACE);
newPic.Click += NewPic_Click;
items.Add(newPic);
this.panel2.Controls.Add(newPic);
}
}
Just for color switching, you only need the PictureBox which has been clicked on. It is stored in the sender parameter.
I you want the coordinates, you need to store some information on the PictureBox. You don't want to specify 50 handlers.
The way I would do is; to make use of the Tag property of a Control.
Your for-loop would be something like:
for (int cols = 0; cols < COLUMNS; cols++)
{
for (int rows = 0; rows < ROWS; rows++)
{
PictureBox newPic = new PictureBox();
newPic.Height = HEIGHT;
newPic.Width = WIDTH;
newPic.BackColor = Color.Maroon;
// instead of the coordinates, store the indices (for col, row)
newPic.Tag = new Point(cols, rows);
// I would use the Width on the cols, instead of the Height.
int x = cols * (WIDTH + SPACE);
int y = rows * (HEIGHT + SPACE);
newPic.Location = new Point(x + SPACE, y + SPACE);
newPic.Click += NewPic_Click;
items.Add(newPic);
this.panel2.Controls.Add(newPic);
}
}
And your handler would be something like:
// a field to store the previous selected picturebox.
private PictureBox _currentPictureBox = null;
private void NewPic_Click(object sender, EventArgs e)
{
// the picturebox which has been clicked, is stored in the sender object, but you need to cast it to a PictureBox.
PictureBox pb = (PictureBox)sender;
// just for the extra use of the Tag.
var location = (Point)pb.Tag;
// location.X Contains the Column index
// location.Y Contains the Row index
// did we have a previous picturebox?
if(_currentPictureBox != null)
{
// change the previous pictureBox back to Maroon
_currentPictureBox.BackColor = Color.Maroon;
}
// change the current to blue
pb.BackColor = Color.Blue;
// store the new one as the current. (so we can revert it)
_currentPictureBox = pb;
}
I haven't tested it, only in a notepad. So there might be some typo's. But I hope you get the idea.

Is possible to draw shapes in C# wpf (grid), if the grid is split by rows and cells, and each row contains a stackpanel inside?

When I try to draw a shape, like a line, is working only in the first StackPanel
Line myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.Y1 = 1;
myLine.X2 = 500;
myLine.Y2 = 50;
// myLine.HorizontalAlignment = HorizontalAlignment.Left;
// myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
gridAreaFight.Children.Add(myLine);
And here is the picture of the grid.
I try to create a Tower Defense game, and I want the towers to attack (with lines/shapes) on the grid, but it seems the draw method is working only in my first stack panel image (see the picture, in the left corner top). Is there something I'm not doing right? Or I should use something else instead drawing method for my towers?
You need to set row and column span for the line in order to draw it in whole available space. If you are drawing something on the grid without specific row and column, it defaults to column and row number 0.
Line myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
Grid.SetRowSpan(myLine, n); // Here you are setting RowSpan. n-number of rows to span
Grid.SetColumnSpan(myLine, n); // Here you are setting ColumnSpan. n-number of columns to span
myLine.X1 = 1;
myLine.Y1 = 1;
myLine.X2 = 500;
myLine.Y2 = 50;
// myLine.HorizontalAlignment = HorizontalAlignment.Left;
// myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
area.Children.Add(myLine);

iTextSharp Duplicating Acrofields

I have an acroform on page 1 of my document. I am creating a blank second page and i would like to show one of the fields on this page as well. If the user changes the value of this field on either of the pages, i want them both to show the new value. I found a few posts that are showing this type of solution but it doesn't work as expected:
PdfFormField fNotes = PdfFormField.CreateTextField(writer, false, false, 500);
string fieldNotes = "tfNotes";
fNotes.FieldName = fieldNotes;
PdfFormField widgetNotes = PdfFormField.CreateEmpty(writer);
PdfPCell notesCell = new PdfPCell(new Paragraph("test", helv8))
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(0, 0, 100, 100), fieldNotes);
writer.AddAnnotation(fNotes);
writer.AddAnnotation(widgetNotes);
In this example, the field on page 1 is named tfNotes. If i understand correctly, i need to create a second widget reference to the acrofield. I think the above code would be for a field that doesn't already exist, in my case it does. Is there an easier way to grab a field by name on page 1 and create a duplicate reference to it on page 2?
Thank you for your time!
EDIT:
This works as expected when i take the table out of the equation, but once i try to put the duplicated field into the PdfPCell it shows up on the page at 0,0 with a width and height of 0. For some reason the rectangle of the cell is returning as 0,0,0,0.
PdfPCell notesCell = new PdfPCell()
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
//Notes Cell Rectangle
float llxNotes = notesCell.GetLeft(0);
float llyNotes = notesCell.GetBottom(0);
float urxNotes = notesCell.GetRight(0);
float uryNotes = notesCell.GetTop(0);
//Notes Duplicate
string fieldNotesName = "tfQuoteNotes";
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(llxNotes, llyNotes, urxNotes, uryNotes), fieldNotesName)
{
FieldName = fieldNotesName
};
tField.SetRotationFromPage(doc.PageSize);
writer.AddAnnotation(tField.GetTextField());
I think all i need to do now is find the correct rectangle coords for the cell.
So the part i was missing was a CellEvent, which i don't completely understand why, but here is the final working snippet for anyone who needs it:
PdfPCell notesCell = new PdfPCell()
{
BorderWidthLeft = 0,
BorderWidthRight = 0,
BorderWidthTop = 0,
BorderWidthBottom = .5f
};
//Notes Cell Rectangle
float llxNotes = notesCell.GetLeft(0);
float llyNotes = notesCell.GetBottom(0);
float urxNotes = notesCell.GetRight(0);
float uryNotes = notesCell.GetTop(0);
//Notes Duplicate
string fieldNotesName = "tfQuoteNotes";
TextField tField = new TextField(writer, new iTextSharp.text.Rectangle(llxNotes, llyNotes, urxNotes, uryNotes), fieldNotesName)
{
FieldName = fieldNotesName
};
tField.SetRotationFromPage(doc.PageSize); //Needed since this page is rotated 90 from the first page
iTextSharp.text.pdf.events.FieldPositioningEvents events = new iTextSharp.text.pdf.events.FieldPositioningEvents(writer, tField.GetTextField());
writer.AddAnnotation(tField.GetTextField());
notesCell.CellEvent = events; //This somehow ignores the original rectangle (0,0,0,0) in the TextField definition above and changes it to the cell's rectangle

Add annotations in MS chart (e.g. (10, 20) (20, 39) etc) and horizontal Scroll Bar

I want to add text(say, annotations) in MS chart(winforms) like (10, 20) , (30, 40) where I already have a scroll bar.
I can able to draw strings(graphics.drawstring) in Chart, but on scrolling the horizontal scroll bar, the text which I have drawn remains static and immovable.
On scrolling the scrollbar, the text which I have drawn also should move along with my horizontal scrolling.
My code follows:
chart2.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart2.BorderlineColor = System.Drawing.Color.FromArgb(26, 59, 105);
chart2.BorderlineWidth = 3;
chart2.BackColor = Color.White;
chart2.ChartAreas.Add("chtArea");
chart2.ChartAreas[0].AxisX.Title = "Category Name";
chart2.ChartAreas[0].AxisX.TitleFont =
new System.Drawing.Font("Verdana", 11, System.Drawing.FontStyle.Bold);
chart2.ChartAreas[0].AxisY.Title = "UnitPrice";
chart2.ChartAreas[0].AxisY.TitleFont =
new System.Drawing.Font("Verdana", 11, System.Drawing.FontStyle.Bold);
chart2.ChartAreas[0].BorderDashStyle = ChartDashStyle.Solid;
chart2.ChartAreas[0].BorderWidth = 2;
chart2.ChartAreas["chtArea"].AxisX.ScrollBar.Enabled = true;
chart2.ChartAreas["chtArea"].CursorX.IsUserEnabled = true;
chart2.ChartAreas["chtArea"].CursorX.IsUserSelectionEnabled = true;
chart2.ChartAreas["chtArea"].AxisX.ScaleView.Zoomable = false;
chart2.ChartAreas["chtArea"].AxisX.ScrollBar.IsPositionedInside = true;
chart2.ChartAreas["chtArea"].AxisX.ScaleView.Size = 20;
chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSizeType = DateTimeIntervalType.Seconds;
chart2.ChartAreas[0].AxisX.ScaleView.SmallScrollSize = 1;
chart2.Legends.Add("UnitPrice");
chart2.Series.Add("UnitPrice");
chart2.Series[0].ChartType = SeriesChartType.Line;
Random rand = new Random();
var valuesArray = Enumerable.Range(0, 500).Select(x => rand.Next(0, 100)).ToArray();
for (int i = 0; i < 500; i++)
{
chart2.Series["UnitPrice"].Points.AddXY(i+10, valuesArray[i]);
}
I tried TextAnnotaions, Line annotations, etc Nothing helped me.
Then I tried drawing dynamic labels inside MS chart also. Labels remain immovable while scrolling horizontal scroll bar.
This code works perfectly in your machine also.
Sounds a lot as if you want to add TextAnnotations.
If you want them to stick with your data points you should anchor them to the points they shall stay with.
Here are a few examples:
// directly anchored to a point
TextAnnotation TA1 = new TextAnnotation();
TA1.Text = "DataPoint 222";
TA1.SetAnchor(chart2.Series["UnitPrice"].Points[222]);
chart2.Annotations.Add(TA1);
// anchored to a point but shifted down
TextAnnotation TA2 = new TextAnnotation();
TA2.Text = "DataPoint 111";
TA2.AnchorDataPoint = chart2.Series["UnitPrice"].Points[111];
TA2.AnchorY = 0;
chart2.Annotations.Add(TA2);
// this one is not anchored on a point:
TextAnnotation TA3 = new TextAnnotation();
TA3.Text = "At 50% width BC";
TA3.AnchorX = 50; // 50% of chart width
TA3.AnchorY = 20; // 20% of chart height, from top!
TA3.Alignment = ContentAlignment.BottomCenter; // try a few!
chart2.Annotations.Add(TA3);
By default they either anchor to DataPoints or are positioned in % of the chart size.
It is also possible to set the positions according to pixel coordinates, but for this you need to calculate the positions each time the chart changes its view!
See here for an example how to transform chart data positions to chart control coordinates and vice versa.. (Not really recommended, though)

How to draw vertical line on mschart that fills graph but isn't infinite?

I am trying to draw a vertical line that is anchored to a point. I tried to use the height of my Y axis which is fixed to draw the line, but it wasn't centered correctly. So right now I have an infinite line, but that I want is the line to just fill the graph like so
VerticalLineAnnotation lineannot = new VerticalLineAnnotation();
lineannot.AnchorDataPoint = chart.Series[item].Points.Last();
lineannot.LineColor = Color.Red;
lineannot.Width = 3;
lineannot.Visible = true;
lineannot.IsInfinitive = true;
chart.Annotations.Add(lineannot);
IsInfinitive is complemented by ClipToChartArea; you can set the line to be clipped to a ChartArea like this:
lineannot.ClipToChartArea = chart.ChartAreas[item].Name;
assuming item is the right area name or index..
Note that ClipToChartArea takes the name of the chart area!
This is the simplest way to do it.
It is also possible to control an annotation's position and size directly:
// Note that directly after adding points this will return NaN:
double maxDataPoint = chart1.ChartAreas[0].AxisY.Maximum;
double minDataPoint = chart1.ChartAreas[0].AxisY.Minimum;
LineAnnotation annotation2 = new LineAnnotation();
annotation2.IsSizeAlwaysRelative = false;
annotation2.AxisX = chart1.ChartAreas[0].AxisX;
annotation2.AxisY = chart1.ChartAreas[0].AxisY;
annotation2.AnchorY = minDataPoint;
annotation2.Height = maxDataPoint - minDataPoint;;
annotation2.Width = 0;
annotation2.LineWidth = 2;
annotation2.StartCap = LineAnchorCapStyle.None;
annotation2.EndCap = LineAnchorCapStyle.None;
annotation2.AnchorX = 21; // <- your point
annotation2.LineColor = Color.Pink; // <- your color
chart1.Annotations.Add(annotation2);

Categories

Resources