I'm giving my panels inside another panel (this panel is in a usercontrol) a fixed location and a maximum size that changes with the size of the panel there in. Neither the resize or location works properly. The resize does happen but its to quickly. The location is fine if you only have 1 pinpanel for output and input. When you have more then 1 the locations are fixed but you need to resize the panel to resize to see the other panels. Could you point me in the right direction if you see the problem?
I have a panel drawPanel in this case that i use as a sort of background for the usercontrol. Inside this drawPanel i'm placing pinpanels. I want these pinpanels to resize with the usercontrol and give them a fixed location
private void OnClickPinPanel(object source, EventArgs e)
{
if (source is PinPanel p)
{
int index;
if ((index = Array.IndexOf(inputPins, p)) >= 0)
{
ClickedPinPanel?.Invoke(index, true);
}
else
{
ClickedPinPanel?.Invoke(Array.IndexOf(outputPins, p), false);
}
}
//else log here
}
private void CreatePinPanels(bool isInput)
{
int x = 0;
int y = -(int)(this.Width * 0.05)/2;
if (isInput)
{
for (int i = 0; i < inputPins.Length; i++)
{
y += (i + 1) * (this.Height / inputPins.Length + 1);
inputPins[i] = new PinPanel()
{
Location = new Point(x, y),
Size = new Size((int)(this.Width * 0.05), (int)(this.Width * 0.05)),
Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right,
};
inputPins[i].Click += OnClickPinPanel;
}
}
else
{
x += this.Width - (int)(this.Width * 0.1);
for (int i = 0; i < outputPins.Length; i++)
{
y += (i + 1) * (this.Height / inputPins.Length+1);
outputPins[i] = new PinPanel()
{
Size = new Size((int)(this.Width * 0.1), (int)(this.Width * 0.1)),
Location = new Point(x, y),
Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right
};
outputPins[i].Click += OnClickPinPanel;
}
}
}
The result i get now is that the pinpanels get a fixed location but when you have more then 1 pinpanel, the location is wrong its like if he thinks that the usercontrol is bigger then it is Reality. In order to see all the pins i have to resize and get this After resize
I want it to look like this
expectations
Try something like this out.
Here is my test rig:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
numericUpDown1.Value = someChip1.NumberInputPins;
numericUpDown2.Value = someChip1.NumberOutputPins;
}
private void numericUpDown1_ValueChanged(object sender, EventArgs e)
{
someChip1.NumberInputPins = (int)numericUpDown1.Value;
}
private void numericUpDown2_ValueChanged(object sender, EventArgs e)
{
someChip1.NumberOutputPins = (int)numericUpDown2.Value;
}
}
Sample chip with 5 inputs and 3 outputs:
Here is my PinPanel UserControl (just draws an ellipse/pin the size of the control):
public partial class PinPanel : UserControl
{
public PinPanel()
{
InitializeComponent();
}
private void PinPanel_Paint(object sender, PaintEventArgs e)
{
Rectangle rc = new Rectangle(new Point(0, 0), new Size(this.ClientRectangle.Width - 1, this.ClientRectangle.Height - 1));
e.Graphics.DrawEllipse(Pens.Black, rc);
}
private void PinPanel_SizeChanged(object sender, EventArgs e)
{
this.Refresh();
}
}
And finally, my SomeChip UserControl:
public partial class SomeChip : UserControl
{
public event PinPanelClick ClickedPinPanel;
public delegate void PinPanelClick(int index, bool input);
private PinPanel[] inputPins;
private PinPanel[] outputPins;
private int _NumberInputPins = 2;
public int NumberInputPins
{
get {
return _NumberInputPins;
}
set
{
if (value > 0 && value != _NumberInputPins)
{
_NumberInputPins = value;
CreatePinPanels();
this.Refresh();
}
}
}
private int _NumberOutputPins = 1;
public int NumberOutputPins
{
get
{
return _NumberOutputPins;
}
set
{
if (value > 0 && value != _NumberOutputPins)
{
_NumberOutputPins = value;
CreatePinPanels();
this.Refresh();
}
}
}
public SomeChip()
{
InitializeComponent();
}
private void SomeChip_Load(object sender, EventArgs e)
{
CreatePinPanels();
RepositionPins();
}
private void SomeChip_SizeChanged(object sender, EventArgs e)
{
this.Refresh();
}
private void SomeChip_Paint(object sender, PaintEventArgs e)
{
int PinHeight;
// draw the input pin runs
if (inputPins != null)
{
PinHeight = (int)((double)this.Height / (double)_NumberInputPins);
for (int i = 0; i < NumberInputPins; i++)
{
int Y = (i * PinHeight) + (PinHeight / 2);
e.Graphics.DrawLine(Pens.Black, 0, Y, this.Width / 4, Y);
}
}
// draw the output pin runs
if (outputPins != null)
{
PinHeight = (int)((double)this.Height / (double)_NumberOutputPins);
for (int i = 0; i < NumberOutputPins; i++)
{
int Y = (i * PinHeight) + (PinHeight / 2);
e.Graphics.DrawLine(Pens.Black, this.Width - this.Width / 4, Y, this.Width, Y);
}
}
//draw the chip itself (takes up 50% of the width of the UserControl)
Rectangle rc = new Rectangle(new Point(this.Width / 4, 0), new Size(this.Width / 2, this.Height - 1));
using (SolidBrush sb = new SolidBrush(this.BackColor))
{
e.Graphics.FillRectangle(sb, rc);
}
e.Graphics.DrawRectangle(Pens.Black, rc);
RepositionPins();
}
private void CreatePinPanels()
{
if (inputPins != null)
{
for (int i = 0; i < inputPins.Length; i++)
{
if (inputPins[i] != null && !inputPins[i].IsDisposed)
{
inputPins[i].Dispose();
}
}
}
inputPins = new PinPanel[_NumberInputPins];
for (int i = 0; i < inputPins.Length; i++)
{
inputPins[i] = new PinPanel();
inputPins[i].Click += OnClickPinPanel;
this.Controls.Add(inputPins[i]);
}
if (outputPins != null)
{
for (int i = 0; i < outputPins.Length; i++)
{
if (outputPins[i] != null && !outputPins[i].IsDisposed)
{
outputPins[i].Dispose();
}
}
}
outputPins = new PinPanel[_NumberOutputPins];
for (int i = 0; i < outputPins.Length; i++)
{
outputPins[i] = new PinPanel();
outputPins[i].Click += OnClickPinPanel;
this.Controls.Add(outputPins[i]);
}
}
private void OnClickPinPanel(object sender, EventArgs e)
{
PinPanel p = (PinPanel)sender;
if (inputPins.Contains(p))
{
ClickedPinPanel?.Invoke(Array.IndexOf(inputPins, p), true);
}
else if (outputPins.Contains(p))
{
ClickedPinPanel?.Invoke(Array.IndexOf(inputPins, p), false);
}
}
private void RepositionPins()
{
int PinRowHeight, PinHeight;
if (inputPins != null)
{
PinRowHeight = (int)((double)this.Height / (double)_NumberInputPins);
PinHeight = (int)Math.Min((double)(PinRowHeight / 2), (double)this.Height * 0.05);
for (int i = 0; i < inputPins.Length; i++)
{
if (inputPins[i] != null && !inputPins[i].IsDisposed)
{
inputPins[i].SetBounds(0, (int)((i * PinRowHeight) + (PinRowHeight /2 ) - (PinHeight / 2)), PinHeight, PinHeight);
}
}
}
if (outputPins != null)
{
PinRowHeight = (int)((double)this.Height / (double)_NumberOutputPins);
PinHeight = (int)Math.Min((double)(PinRowHeight / 2), (double)this.Height * 0.05);
for (int i = 0; i < outputPins.Length; i++)
{
if (outputPins[i] != null && !outputPins[i].IsDisposed)
{
outputPins[i].SetBounds(this.Width - PinHeight, (int)((i * PinRowHeight) + (PinRowHeight / 2) - (PinHeight / 2)), PinHeight, PinHeight);
}
}
}
}
}
Related
I'm using MaterialSkin UI controls , how can I change the control properties to Right to left, because it's by default Left to Right.
I think this is the code should be edited :
private void UpdateTabRects()
{
_tabRects = new List<Rectangle>();
//If there isn't a base tab control, the rects shouldn't be calculated
//If there aren't tab pages in the base tab control, the list should just be empty which has been set already; exit the void
if (_baseTabControl == null || _baseTabControl.TabCount == 0) return;
//Calculate the bounds of each tab header specified in the base tab control
using (var b = new Bitmap(1, 1))
{
using (var g = Graphics.FromImage(b))
{
_tabRects.Add(new Rectangle(SkinManager.FormPadding, 0, TabHeaderPadding * 2 + (int)g.MeasureString(_baseTabControl.TabPages[0].Text, SkinManager.Font_Size11).Width, Height));
for (int i = 1; i < _baseTabControl.TabPages.Count; i++)
{
_tabRects.Add(new Rectangle(_tabRects[i - 1].Right, 0, TabHeaderPadding * 2 + (int)g.MeasureString(_baseTabControl.TabPages[i].Text , SkinManager.Font_Size11).Width , Height));
}
}
}
}
and this is the full code for the control :
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Windows.Forms;
using MaterialSkin.Animations;
namespace MaterialSkin.Controls
{
public class MaterialTabSelector : Control, IMaterialControl
{
[Browsable(false)]
public int Depth { get; set; }
[Browsable(false)]
public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;
[Browsable(false)]
public MouseState MouseState { get; set; }
private MaterialTabControl _baseTabControl;
public MaterialTabControl BaseTabControl
{
get { return _baseTabControl; }
set
{
_baseTabControl = value;
if (_baseTabControl == null) return;
_previousSelectedTabIndex = _baseTabControl.SelectedIndex;
_baseTabControl.Deselected += (sender, args) =>
{
_previousSelectedTabIndex = _baseTabControl.SelectedIndex;
};
_baseTabControl.SelectedIndexChanged += (sender, args) =>
{
_animationManager.SetProgress(0);
_animationManager.StartNewAnimation(AnimationDirection.In);
};
_baseTabControl.ControlAdded += delegate
{
Invalidate();
};
_baseTabControl.ControlRemoved += delegate
{
Invalidate();
};
}
}
private int _previousSelectedTabIndex;
private Point _animationSource;
private readonly AnimationManager _animationManager;
private List<Rectangle> _tabRects;
private const int TabHeaderPadding = 24;
private const int TabIndicatorHeight = 2;
public MaterialTabSelector()
{
SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer, true);
Height = 48;
_animationManager = new AnimationManager
{
AnimationType = AnimationType.EaseOut,
Increment = 0.04
};
_animationManager.OnAnimationProgress += sender => Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
var g = e.Graphics;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.Clear(SkinManager.ColorScheme.PrimaryColor);
if (_baseTabControl == null) return;
if (!_animationManager.IsAnimating() || _tabRects == null || _tabRects.Count != _baseTabControl.TabCount)
UpdateTabRects();
var animationProgress = _animationManager.GetProgress();
//Click feedback
if (_animationManager.IsAnimating())
{
var rippleBrush = new SolidBrush(Color.FromArgb((int)(51 - (animationProgress * 50)), Color.White));
var rippleSize = (int)(animationProgress * _tabRects[_baseTabControl.SelectedIndex].Width * 1.75);
g.SetClip(_tabRects[_baseTabControl.SelectedIndex]);
g.FillEllipse(rippleBrush, new Rectangle(_animationSource.X - rippleSize / 2, _animationSource.Y - rippleSize / 2, rippleSize, rippleSize));
g.ResetClip();
rippleBrush.Dispose();
}
//Draw tab headers
foreach (TabPage tabPage in _baseTabControl.TabPages)
{
var currentTabIndex = _baseTabControl.TabPages.IndexOf(tabPage);
Brush textBrush = new SolidBrush(Color.FromArgb(CalculateTextAlpha(currentTabIndex, animationProgress), SkinManager.ColorScheme.TextColor));
g.DrawString(tabPage.Text.ToUpper(), SkinManager.Font_Size11, textBrush, _tabRects[currentTabIndex], new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
textBrush.Dispose();
}
//Animate tab indicator
var previousSelectedTabIndexIfHasOne = _previousSelectedTabIndex == -1 ? _baseTabControl.SelectedIndex : _previousSelectedTabIndex;
var previousActiveTabRect = _tabRects[previousSelectedTabIndexIfHasOne];
var activeTabPageRect = _tabRects[_baseTabControl.SelectedIndex];
var y = activeTabPageRect.Bottom - 2;
var x = previousActiveTabRect.X + (int)((activeTabPageRect.X - previousActiveTabRect.X) * animationProgress);
var width = previousActiveTabRect.Width + (int)((activeTabPageRect.Width - previousActiveTabRect.Width) * animationProgress);
g.FillRectangle(SkinManager.ColorScheme.AccentBrush, x, y, width, TabIndicatorHeight);
}
private int CalculateTextAlpha(int tabIndex, double animationProgress)
{
int primaryA = SkinManager.ActionBarText.A;
int secondaryA = SkinManager.ActionBarTextSecondary.A;
if (tabIndex == _baseTabControl.SelectedIndex && !_animationManager.IsAnimating())
{
return primaryA;
}
if (tabIndex != _previousSelectedTabIndex && tabIndex != _baseTabControl.SelectedIndex)
{
return secondaryA;
}
if (tabIndex == _previousSelectedTabIndex)
{
return primaryA - (int)((primaryA - secondaryA) * animationProgress);
}
return secondaryA + (int)((primaryA - secondaryA) * animationProgress);
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if (_tabRects == null) UpdateTabRects();
for (var i = 0; i < _tabRects.Count; i++)
{
if (_tabRects[i].Contains(e.Location))
{
_baseTabControl.SelectedIndex = i;
}
}
_animationSource = e.Location;
}
private void UpdateTabRects()
{
_tabRects = new List<Rectangle>();
//If there isn't a base tab control, the rects shouldn't be calculated
//If there aren't tab pages in the base tab control, the list should just be empty which has been set already; exit the void
if (_baseTabControl == null || _baseTabControl.TabCount == 0) return;
//Calculate the bounds of each tab header specified in the base tab control
using (var b = new Bitmap(1, 1))
{
using (var g = Graphics.FromImage(b))
{
_tabRects.Add(new Rectangle(SkinManager.FormPadding, 0, TabHeaderPadding * 2 + (int)g.MeasureString(_baseTabControl.TabPages[0].Text, SkinManager.Font_Size11).Width, Height));
for (int i = 1; i < _baseTabControl.TabPages.Count; i++)
{
_tabRects.Add(new Rectangle(_tabRects[i - 1].Right, 0, TabHeaderPadding * 2 + (int)g.MeasureString(_baseTabControl.TabPages[i].Text , SkinManager.Font_Size11).Width , Height));
}
}
}
}
}
}
If you're using windows forms you would go into the properties of the tab control and make:
RightToLeft = Yes
and
RightToLeftLayout = True.
This is also a duplicate question:
How to make Managed Tab Control (MTC) appear right to left
I've got a User Control consisting of Panels and Labels.
MinPanel, ValuePanel, and MaxPanel.
I'm trying to allow the user to drag the panels much like you would in a TrackBar.
My problem is that when I click and attempt to drag the MinPanel, it jump around starting at 0, then to 200, then to other random values. It seems to be attempting to reset to it's default value each time I drag it.
public partial class ToolboxCustomTrackBar : UserControl
{
private int min = 0;
private int max = 1000;
private int selectedMin = 0;
private int selectedMax = 1000;
private int selectedValue = 400;
private int selectionWidth = 0;
private int labelHeight = 10;
public int Min
{
get { return min; }
set
{
min = value;
Invalidate();
}
}
public int Max
{
get { return max; }
set
{
max = value;
Invalidate();
}
}
public int SelectedMin
{
get { return selectedMin; }
set
{
selectedMin = value;
Invalidate();
}
}
public int SelectedMax
{
get { return selectedMax; }
set
{
selectedMax = value;
Invalidate();
}
}
public int SelectedValue
{
get { return selectedValue; }
set { selectedValue = value; Invalidate(); }
}
public int LabelHeight
{
get { return labelHeight; }
set { labelHeight = value; Invalidate(); }
}
public ToolboxCustomTrackBar()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
backdropPanel.Width = Width;
backdropPanel.Height = Height;
SelectedMin = Min;
SelectedMax = Max;
SelectedValue = (Max - Min) / 2;
selectionWidth = Max - Min;
Invalidate();
backdropPanel.BackColor = Color.LightBlue;
minPanel.BackColor = Color.DarkRed;
maxPanel.BackColor = Color.DarkGreen;
valuePanel.BackColor = Color.Black;
backdropPanel.Location = new Point(Min, backdropPanel.Location.Y);
}
private void ToolboxCustomTrackBar_Paint(object sender, PaintEventArgs e)
{
backdropPanel.Location = new Point(0, LabelHeight);
backdropPanel.Width = Width;
backdropPanel.BackColor = Color.AliceBlue;
minPanel.Location = new Point(SelectedMin * Width / (Max - Min), backdropPanel.Location.Y);
maxPanel.Location = new Point(SelectedMax * Width / (Max - Min), backdropPanel.Location.Y);
valuePanel.Location = new Point((SelectedValue) * Width / (Max - Min), backdropPanel.Location.Y);
minLabel.Location = new Point(SelectedMin - (minLabel.Width / 2) + (minPanel.Width / 2), backdropPanel.Location.Y - LabelHeight);
minLabel.Text = SelectedMin.ToString();
maxLabel.Location = new Point(SelectedMax - (maxLabel.Width / 2) + (maxPanel.Width / 2), backdropPanel.Location.Y - LabelHeight);
maxLabel.Text = SelectedMax.ToString();
valueLabel.Location = new Point(SelectedValue - (valueLabel.Width / 2) + (valuePanel.Width / 2), backdropPanel.Location.Y - LabelHeight);
valueLabel.Text = SelectedValue.ToString();
}
private void minPanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return; //ensure user left-clicked
int pointedValue = Min + e.X * (Max - Min) / Width; //selectionWidth?
SelectedMin = pointedValue;
}
}
I've cut some unrelated bits out.
I don't fully understand why, but I need to use += instead of =.
private void minPanel_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button != MouseButtons.Left) return; //ensure user left-clicked
int pointedValue = Min + e.X * (Max - Min) / Width;
SelectedMin += pointedValue;
}
I'm currently trying to make a new class named GameButton in Visual Studio Community. im trying to put all the code into it, so that all the code is generated from the button instead of the form, but now that i moved most of the code, it either doesnt show up, or goes into an infinite loop, and im not sure how to fix it at this point. if i didnt give enough information i will supply more if needed.
(Speelveld is a form inside of the form that determines the location of the buttons. The "speelveld" is a Panel imported from the built in toolbox in visual studio. Then the code refrences to that form to build the buttons into.)
Form c#
namespace WindowsFormsApplication9
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Marble();
}
public void Marble()
{
string line;
System.IO.StreamReader file = new System.IO.StreamReader("Bitmap.txt");
int ButtonHeight = 40;
int y_row = 0;
GameButton testButton = new GameButton();
while ((line = file.ReadLine()) != null)
{
for (int x_row = 0; x_row < line.Count(); x_row++)
{
if(line.Substring(x_row, 1) == "1")
{
Speelveld.BackColor = Color.White;
BackColor = Color.White;
testButton.Currentcolor = false;
if (x_row == 4 && y_row == 6)
{
testButton.BackColor = Color.White;
}
else
{
Speelveld.Controls.Add(testButton);
}
}
}
y_row++;
}
}
}
}
GameButton c#
namespace WindowsFormsApplication9
{
public class GameButton: Button
{
public int Row { get; set; }
public int Column { get; set; }
public bool Currentcolor { get; set; }
Pen myPen;
public int ButtonHeight = 40;
public int y_row = 0;
public int x_row = 0;
public void Startup()
{
this.BackColor = Color.Red;
this.Height = ButtonHeight;
this.Width = ButtonHeight;
this.Top = y_row * ButtonHeight + 20;
this.Left = x_row * ButtonHeight + 20;
this.Text = "X: " + x_row.ToString() + " Y: " + y_row.ToString();
this.MouseUp += TmpButton_MouseUp;
}
protected override void OnPaint(PaintEventArgs pevent)
{
int radius = 20;
pevent.Graphics.Clear(Color.White);
Graphics graphics = pevent.Graphics;
myPen = new Pen(new SolidBrush(this.BackColor), 2f);
pevent.Graphics.FillEllipse(new SolidBrush(this.BackColor), 20 - radius, 20 - radius,
radius + radius, radius + radius);
myPen.Dispose();
}
private void TmpButton_MouseUp(object sender, MouseEventArgs e)
{
GameButton Mygamebutton = (GameButton)sender;
Mygamebutton.Currentcolor = !Mygamebutton.Currentcolor;
if (Mygamebutton.Currentcolor == true)
{
Mygamebutton.BackColor = Color.Black;
}
else
{
Mygamebutton.BackColor = Color.White;
}
}
}
}
BitMap.txt
011111110
111111111
111111111
011111110
001111100
000111000
000010000
There are several mistakes in your coed. you didn't call testButton.Startup() to set its position, also the GameButton class needs to know that x_row, y_row values...
please see following:
public void Marble()
{
string line;
System.IO.StreamReader file = new System.IO.StreamReader(#"C:\Users\Main\Desktop\Bitmap.txt");
//var Speelveld = new Form3();
//Speelveld.Show();
int y_row = 0;
while ((line = file.ReadLine()) != null)
{
for (int x_row = 0; x_row < line.Count(); x_row++)
{
if (line.Substring(x_row, 1) == "1")
{
Speelveld.BackColor = Color.White;
BackColor = Color.White;
GameButton testButton = new GameButton(); // ***
testButton.Currentcolor = false;
if (x_row == 4 && y_row == 6)
{
testButton.BackColor = Color.White;
}
else
{
Speelveld.Controls.Add(testButton);
testButton.Startup(x_row , y_row); //***
}
}
}
y_row++;
}
}
and add these in GameButton startup:
public void Startup(int x, int y) //***
{
this.x_row = x; //***
this.y_row = y; //***
...
}
I had to implement a way to navigate between different element that are stacked in xamarin.forms. In the code below, you can see that we already manage the ability to distinguish every single one of the child of the container. At the moment, what I have written works but I need some help figuring out if it’s the good way or if there is a better way or even, if I can improve what I’ve done.
Currently, when you swipe from left to right or whatever move, I just use a SimpleOnGestureListener.
Here are some samples of what we are currently achieving:
I declared my custom elements such as the container & the children and then I created the customRenderer for each of them in an android library (only working on android at the moment).
“MyContent” is simply a modified frame with a specific Draw method and an event for each move available (up, down, left, right).
Code of the container
using System;
using Xamarin.Forms;
namespace Elements
{
public class MyContainer : Layout<MyContent>
{
public MyContainer ()
{
}
protected override void LayoutChildren (double x, double y, double width, double height)
{
for (int i = 0; i < Children.Count ; i++) {
MyContent child = Children[i];
// skip invisible children
if(!child.IsVisible)
continue;
int soffset = Children.Count - i;
int eoffset = soffset - 1;
Rectangle startBoundingRegion = new Rectangle (12 * soffset + Padding.Left, 14 * soffset + Padding.Top, width - 24 * soffset, height - 8 * soffset);
Rectangle endBoundingRegion = new Rectangle (12 * eoffset + Padding.Left, 14 * eoffset + Padding.Top, width - 24 * eoffset, height - 8 * eoffset);
child.OriginalBounds = endBoundingRegion;
LayoutChildIntoBoundingRegion (child,startBoundingRegion);
child.LayoutTo(endBoundingRegion,100,Easing.Linear);
}
}
protected override SizeRequest OnSizeRequest (double widthConstraint, double heightConstraint)
{
var height = 0;
var minHeight = 0;
var width = 0;
var minWidth = 0;
for (int i = 0; i < Children.Count; i++) {
MyContent child = Children[i];
// skip invisible children
if(!child.IsVisible)
continue;
var childSizeRequest = child.GetSizeRequest (double.PositiveInfinity, height);
height = (int)Math.Max (height, childSizeRequest.Minimum.Height);
minHeight = (int)Math.Max (minHeight, childSizeRequest.Minimum.Height);
width += (int)childSizeRequest.Request.Width;
minWidth += (int)childSizeRequest.Minimum.Width;
}
return new SizeRequest (new Size (width, height), new Size (minWidth, minHeight));
}
}
}
Code of its renderer
{using ...}
[assembly: ExportRenderer (typeof(MyContainer), typeof(MyContainerRenderer))]
namespace MyApp
{
public class MyContainerRenderer : ViewRenderer<Layout<MyContent>,Android.Views.View>
{
private readonly MyContentGestureListener listener;
private readonly GestureDetector detector;
private bool isAnimating;
private MyContent currentMyContent;
public MyContainerRenderer ()
{
listener = new MyContentGestureListener();
detector = new GestureDetector(listener);
}
protected override void OnElementChanged (ElementChangedEventArgs<Layout<MyContent>> e)
{
base.OnElementChanged(e);
if (e.NewElement == null)
{
this.Touch -= HandleTouch;
listener.OnSwipeLeft -= HandleOnSwipeLeft;
listener.OnSwipeRight -= HandleOnSwipeRight;
listener.OnSwipeTop -= HandleOnSwipeTop;
listener.OnSwipeDown -= HandleOnSwipeDown;
listener.OnPanVertical -= HandleOnPanVertical;
listener.OnPanHorizontal -= HandleOnPanHorizontal;
}
if (e.OldElement == null)
{
this.Touch += HandleTouch;
listener.OnSwipeLeft += HandleOnSwipeLeft;
listener.OnSwipeRight += HandleOnSwipeRight;
listener.OnSwipeTop += HandleOnSwipeTop;
listener.OnSwipeDown += HandleOnSwipeDown;
listener.OnPanVertical += HandleOnPanVertical;
listener.OnPanHorizontal += HandleOnPanHorizontal;
}
}
void HandleTouch(object sender, TouchEventArgs e)
{
currentMyContent = ((MyContainer)this.Element).Children.Last();
if (!isAnimating) {
if (e.Event.Action == MotionEventActions.Down) {
currentMyContent.ScaleTo (1.01, 100, Easing.Linear);
} else if ( e.Event.Action == MotionEventActions.Up){
if (!isAnimating) {
isAnimating = true;
currentMyContent.ScaleTo (1, 100, Easing.Linear);
currentMyContent.LayoutTo (currentMyContent.OriginalBounds, 100, Easing.CubicIn);
isAnimating = false;
listener.ResetFlags ();
}
}
detector.OnTouchEvent (e.Event);
}
}
void HandleOnPanVertical(object sender, EventArgs distanceY)
{
Rectangle dest = new Rectangle (currentMyContent.Bounds.X,currentMyContent.Bounds.Y - ((EventArgs<float>)distanceY).Value,currentMyContent.Bounds.Width,currentMyContent.Bounds.Height);
currentMyContent.Layout(dest);
}
void HandleOnPanHorizontal(object sender, EventArgs distanceX)
{
Rectangle dest = new Rectangle (currentMyContent.Bounds.X - ((EventArgs<float>)distanceX).Value,currentMyContent.Bounds.Y,currentMyContent.Bounds.Width,currentMyContent.Bounds.Height);
currentMyContent.Layout (dest);
}
async void animateNext (MyContent mContent, Rectangle dest)
{
isAnimating = true;
await mContent.LayoutTo (dest, 150, Easing.Linear);
((MyContainer)this.Element).Children.Remove (mContent);
((MyContainer)this.Element).Children.Insert (0, mContent);
isAnimating = false;
}
void HandleOnSwipeLeft(object sender, EventArgs e)
{
currentMyContent.OnSwipeLeft();
Rectangle dest = new Rectangle (currentMyContent.Bounds.X,currentMyContent.Bounds.Y,currentMyContent.Bounds.Width,currentMyContent.Bounds.Height);
dest.Left -= Width;
animateNext (currentMyContent, dest);
}
void HandleOnSwipeRight(object sender, EventArgs e)
{
currentMyContent.OnSwipeRight();
Rectangle dest = new Rectangle (currentMyContent.Bounds.X,currentMyContent.Bounds.Y,currentMyContent.Bounds.Width,currentMyContent.Bounds.Height);
dest.Left += Width;
animateNext (currentMyContent, dest);
}
void HandleOnSwipeTop(object sender, EventArgs e)
{
Rectangle dest = new Rectangle (currentMyContent.Bounds.X, currentMyContent.Bounds.Y, currentMyContent.Bounds.Width, currentMyContent.Bounds.Height);
dest.Top -= Height;
animateNext (currentMyContent, dest);
}
void HandleOnSwipeDown(object sender, EventArgs e)
{
Rectangle dest = new Rectangle (currentMyContent.Bounds.X,currentMyContent.Bounds.Y,currentMyContent.Bounds.Width,currentMyContent.Bounds.Height);
dest.Top += Height;
animateNext (currentMyContent, dest);
}
}
class MyContentGestureListener : GestureDetector.SimpleOnGestureListener
{
private static int SWIPE_THRESHOLD = 50;
private static int SWIPE_VELOCITY_THRESHOLD = 20;
private bool isPanningV;
private bool isPanningH;
public event EventHandler OnSwipeDown;
public event EventHandler OnSwipeTop;
public event EventHandler OnSwipeLeft;
public event EventHandler OnSwipeRight;
public event EventHandler OnPanHorizontal;
public event EventHandler OnPanVertical;
public override bool OnScroll(MotionEvent ev1, MotionEvent ev2,float distanceX,float distanceY)
{
if (Math.Abs (distanceX) > Math.Abs (distanceY) && OnPanHorizontal != null && !isPanningV) {
isPanningH = true;
OnPanHorizontal (this,new EventArgs<float> (distanceX));
} else if (OnPanVertical != null && !isPanningH) {
isPanningV = true;
OnPanVertical (this, new EventArgs<float> (distanceY));
}
return base.OnScroll (ev1, ev2, distanceX, distanceY);
}
public override bool OnFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
float diffY = e2.GetY() - e1.GetY();
float diffX = e2.GetX() - e1.GetX();
if (Math.Abs(diffX) > Math.Abs(diffY) && Math.Abs(diffX) > SWIPE_THRESHOLD && Math.Abs(velocityX) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffX > 0 && OnSwipeRight != null)
{
OnSwipeRight (this, null);
isPanningH = false;
}
else if (OnSwipeLeft != null) {
OnSwipeLeft (this, null);
isPanningH = false;
}
}
else if (Math.Abs(diffY) > SWIPE_THRESHOLD && Math.Abs(velocityY) > SWIPE_VELOCITY_THRESHOLD)
{
if (diffY > 0 && OnSwipeDown != null)
{
OnSwipeDown (this, null);
isPanningV = false;
}
else if (OnSwipeTop != null) {
OnSwipeTop (this, null);
isPanningV = false;
}
}
return base.OnFling (e1, e2, velocityX, velocityY);
}
public void ResetFlags(){
isPanningH = false;
isPanningV = false;
}
}
public class EventArgs<T> : EventArgs
{
public EventArgs(T value)
{
Value = value;
}
public T Value { get; private set; }
}
}
I've a txt file with a 360 numbers, I must read all of these and draw a kind of Disc made of FillPie eachone colored in scale of grey due to the value of the list. Until here everything is quite simple.I made a class with the data(value in the txt and degree) of one single fillpie with a Paint method that draw it of the correct color.
this is the code of the class:
class DatoDisco
{
int valoreSpicchio;
int gradi;
public DatoDisco(int valoreTastatore, int gradiLettura)
{
valoreSpicchio = valoreTastatore;
gradi = gradiLettura;
}
public void Clear()
{
valoreSpicchio = 0;
gradi = 0;
}
private int ScalaGrigi()
{
int grigio = 0;
if (valoreSpicchio <= 0)
{
grigio = 125 + (valoreSpicchio / 10);
if (grigio < 0)
grigio = 0;
}
if (valoreSpicchio > 0)
{
grigio = 125 + (valoreSpicchio / 10);
if (grigio > 230)
grigio = 230;
}
return grigio;
}
public void Paint (Graphics grafica)
{
try
{
Brush penna = new SolidBrush(Color.FromArgb(255, ScalaGrigi(), ScalaGrigi(), ScalaGrigi()));
grafica.FillPie(penna, 0, 0, 400, 400, gradi, 1.0f);
}
catch
{
}
}
public int ValoreSpicchio
{
get
{
return valoreSpicchio;
}
}
public int Gradi
{
get
{
return gradi;
}
}
}
here is where I draw everything:
public partial class Samac : Form
{
libnodave.daveOSserialType fds;
libnodave.daveInterface di;
libnodave.daveConnection dc;
int rack = 0;
int slot = 2;
int scalaGrigi = 0;
int angolatura = 0;
List<int> valoriY = new List<int>();
//Disco disco = new Disco();
List<DatoDisco> disco = new List<DatoDisco>();
float[] valoriTastatore = new float[360];
public Samac()
{
InitializeComponent();
StreamReader dataStream = new StreamReader("save.txt");
textBox1.Text = dataStream.ReadLine();
dataStream.Dispose();
for (int i = 0; i <= 360; i++ )
chart1.Series["Series2"].Points.Add(0);
//AggiornaGrafico(textBox1.Text, chart1);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
}
string indirizzoIpPlc
{
get
{
FileIniDataParser parser = new FileIniDataParser();
IniData settings = parser.LoadFile("config.ini");
return settings["PLC_CONNECTION"]["PLC_IP"];
}
}
private void AggiornaGrafico(string nomeFile, Chart grafico, bool online)
{
int max = 0;
int min = 0;
grafico.Series["Series1"].Points.Clear();
grafico.Series["Series2"].Points.Clear();
grafico.Series["Series3"].Points.Clear();
grafico.Series["Series4"].Points.Clear();
grafico.ChartAreas[0].AxisX.Maximum = 360;
grafico.ChartAreas[0].AxisX.Minimum = 0;
grafico.ChartAreas[0].AxisY.Maximum = 500;
grafico.ChartAreas[0].AxisY.Minimum = -500;
String file = nomeFile;
valoriY.Clear();
disco.Clear();
if (online == false)
{
System.IO.File.WriteAllText("save.txt", nomeFile);
}
StreamReader dataStreamGrafico = new StreamReader(file);
StreamReader dataStreamScheda = new StreamReader("Scheda.sch");
string datasample;
string[] scheda = new string[56];
for (int i = 0; i < 56; i++)
{
scheda[i] = dataStreamScheda.ReadLine();
}
dataStreamScheda.Close();
int gradi = 1;
while ((datasample = dataStreamGrafico.ReadLine()) != null)
{
grafico.Series["Series2"].Points.Add(0);
grafico.Series["Series2"].Color = Color.Red;
grafico.Series["Series2"].BorderWidth = 3;
grafico.Series["Series3"].Points.Add(Convert.ToInt32(float.Parse(scheda[5])));
grafico.Series["Series3"].Color = Color.Green;
grafico.Series["Series3"].BorderWidth = 3;
grafico.Series["Series4"].Points.Add(Convert.ToInt32(-float.Parse(scheda[5])));
grafico.Series["Series4"].Color = Color.Green;
grafico.Series["Series4"].BorderWidth = 3;
grafico.Series["Series1"].Points.Add(int.Parse(datasample));
grafico.Series["Series1"].BorderWidth = 5;
valoriY.Add(int.Parse(datasample));
//disco.Add(int.Parse(datasample));
disco.Add(new DatoDisco(int.Parse(datasample), gradi));
gradi++;
}
dataStreamGrafico.Close();
max = Convert.ToInt32(chart1.Series["Series1"].Points.FindMaxByValue().YValues[0]);
min = Convert.ToInt32(chart1.Series["Series1"].Points.FindMinByValue().YValues[0]);
lblCampanatura.Text = (((float)max + min) / 2000.0).ToString();
lblSbandieramento.Text = (((float)max - min) / 1000.0).ToString();
if ((Math.Abs(max) > 800) || (Math.Abs(min) > 800))
{
if (Math.Abs(max) >= Math.Abs(min))
{
chart1.ChartAreas[0].AxisY.Maximum = max + 200;
chart1.ChartAreas[0].AxisY.Minimum = -(max + 200);
}
else
{
chart1.ChartAreas[0].AxisY.Maximum = min + 200;
chart1.ChartAreas[0].AxisY.Minimum = -(min + 200);
}
}
else
{
chart1.ChartAreas[0].AxisY.Maximum = 800;
chart1.ChartAreas[0].AxisY.Minimum = -800;
}
boxGraficaDisco.Refresh();
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult result = openFileDialog1.ShowDialog();
textBox1.Text = openFileDialog1.FileName;
if (result == DialogResult.OK)
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
}
ToolTip tooltip = new ToolTip();
private int lastX;
private int lastY;
private void chart1_MouseMove(object sender, MouseEventArgs e)
{
if (e.X != this.lastX || e.Y != this.lastY)
{
try
{
int cursorX = Convert.ToInt32(chart1.ChartAreas[0].AxisX.PixelPositionToValue(e.Location.X));
tooltip.Show("X:" + cursorX.ToString("0.00") + "Y:" + Convert.ToInt32(chart1.Series[0].Points[cursorX].YValues[0]).ToString(), this.chart1, e.Location.X + 20, e.Location.Y + 20);
}
catch { }
}
this.lastX = e.X;
this.lastY = e.Y;
}
private void button1_Click_1(object sender, EventArgs e)
{
int indice = ((int)Char.GetNumericValue(textBox1.Text[textBox1.Text.Length - 5]))+1;
if (File.Exists(textBox1.Text.Substring(0, textBox1.Text.Length - 5) + indice + ".txt"))
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 5) + indice + ".txt";
try
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
catch
{
MessageBox.Show("Il File non esiste");
}
}
else
{
MessageBox.Show("Il File non esiste");
}
}
private void btnGrafMeno_Click(object sender, EventArgs e)
{
int indice = ((int)Char.GetNumericValue(textBox1.Text[textBox1.Text.Length - 5])) - 1;
if (indice >= 0)
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 5) + indice + ".txt";
try
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
catch
{
MessageBox.Show("Il File non esiste");
}
}
else
{
MessageBox.Show("Prima lettura disco");
}
}
private void btnConnetti_Click(object sender, EventArgs e)
{
fds.rfd = libnodave.openSocket(102, indirizzoIpPlc);
fds.wfd = fds.rfd;
if (fds.rfd > 0)
{
di = new libnodave.daveInterface(fds, "IF1", 0, libnodave.daveProtoISOTCP, libnodave.daveSpeed187k);
di.setTimeout(1000000);
dc = new libnodave.daveConnection(di, 0, rack, slot);
int res = dc.connectPLC();
timer1.Start();
// AggiornaGrafico("Disco.csv", chart1, timer1.Enabled);
}
else
{
MessageBox.Show("Impossibile connettersi");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
int res;
res = dc.readBytes(libnodave.daveDB, 21, 40, 1, null);
if (res == 0)
{
var letturaDati = (dc.getS8At(0) & (1 << 0)) != 0;
if (letturaDati == true)
{
int puntatore = 30;
StreamWriter datiDisco = new StreamWriter("DatiDaPlc.csv");
datiDisco.WriteLine("X;" + "C;" + "Z;");
while (puntatore <= 10838)
{
res = dc.readBytes(libnodave.daveDB, 3, puntatore, 192, null);
if (res == 0)
{
for (int i = 0; dc.getU32At(i) != 0; i = i + 12)
{
datiDisco.Write(dc.getU32At(i).ToString() + ";");
datiDisco.Write(dc.getU32At(i + 4).ToString() + ";");
datiDisco.WriteLine(dc.getFloatAt(i + 8).ToString() + ";");
}
}
puntatore = puntatore + 192;
}
datiDisco.Close();
StreamReader lettura = new StreamReader("DatiDaPlc.csv");
StreamWriter scritt = new StreamWriter("Disco.csv");
var titolo = lettura.ReadLine();
var posizioneLettura = lettura.ReadLine();
var posX = posizioneLettura.Split(';');
int minX = Convert.ToInt32(posX[0]) - 5;
int maxX = Convert.ToInt32(posX[0]) + 5;
int contatore = 0;
while (!lettura.EndOfStream)
{
var line = lettura.ReadLine();
var values = line.Split(';');
if ((Convert.ToInt32(values[1]) >= contatore && Convert.ToInt32(values[1]) < contatore + 1000) && (Convert.ToInt32(values[0]) > minX && Convert.ToInt32(values[0]) <= maxX))
{
scritt.WriteLine(Convert.ToInt32(float.Parse(values[2]) * 1000).ToString());
contatore += 1000;
}
}
lettura.Close();
scritt.Close();
AggiornaGrafico("Disco.csv", chart1, timer1.Enabled);
}
}
else
{
timer1.Stop();
MessageBox.Show("Disconnesso");
dc.disconnectPLC();
di.disconnectAdapter();
fds.rfd = libnodave.closeSocket(102);
fds.wfd = fds.rfd;
}
}
}
private void btnDisconnetti_Click(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
dc.disconnectPLC();
di.disconnectAdapter();
fds.rfd = libnodave.closeSocket(102);
fds.wfd = fds.rfd;
timer1.Stop();
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
}
private void Samac_FormClosing(object sender, FormClosingEventArgs e)
{
if (timer1.Enabled == true)
{
dc.disconnectPLC();
di.disconnectAdapter();
libnodave.closeSocket(102);
timer1.Stop();
}
}
private void button1_Click_2(object sender, EventArgs e)
{
if (timer1.Enabled == true)
{
AggiornaGrafico("Disco.csv", chart1, timer1.Enabled);
}
else
{
AggiornaGrafico(textBox1.Text, chart1, timer1.Enabled);
}
}
private void chart2_MouseMove(object sender, MouseEventArgs e)
{
if (e.X != this.lastX || e.Y != this.lastY)
{
try
{
int cursorX = Convert.ToInt32(chart2.ChartAreas[0].AxisX.PixelPositionToValue(e.Location.X));
int cursorY = Convert.ToInt32(chart2.ChartAreas[0].AxisY.PixelPositionToValue(e.Location.Y));
//tooltip.Show("X:" + chart2.Series[0].Points[cursorX].XValue.ToString() + "Y:" + chart2.Series[0].Points[cursorX].YValues[0].ToString(), this.chart2, e.Location.X + 20, e.Location.Y + 20);
tooltip.Show("X:" + cursorX.ToString() + "Y:#VALY" , this.chart2, e.Location.X + 20, e.Location.Y + 20);
//chart2.Series[0].ToolTip="#VALY";
}
catch { }
}
this.lastX = e.X;
this.lastY = e.Y;
}
private void boxGraficaDisco_Paint(object sender, PaintEventArgs e)
{
Graphics grafica = e.Graphics;
//disco.Paint(grafica);
foreach (DatoDisco d in disco)
{
d.Paint(grafica);
}
}
private void boxGraficaDisco_MouseMove(object sender, MouseEventArgs e)
{
if (e.X != this.lastX || e.Y != this.lastY)
{
try
{
foreach (DatoDisco d in disco)
{
}
}
catch { }
}
this.lastX = e.X;
this.lastY = e.Y;
}
}
Now I need that when i go with the mouse over the drawn disc, a tooltip show me the data of the fillPie(degree and value of txt) but i can't figure out how.
Anyone can help me?
this is an image of the disc
Eventually it looks as if all you want is a function to get the angle between the mouse position and the center of the disc..
Here is a function to calculate an angle given two points:
double AngleFromPoints(Point pt1, Point pt2)
{
Point P = new Point(pt1.X - pt2.X, pt1.Y - pt2.Y);
double alpha = 0d;
if (P.Y == 0) alpha = P.X > 0 ? 0d : 180d;
else
{
double f = 1d * P.X / (Math.Sqrt(P.X * P.X + P.Y * P.Y));
alpha = Math.Acos(f) * 180d / Math.PI;
if (P.Y > 0) alpha = 360d - alpha;
}
return alpha;
}