MaterialSkin Right to Left custom Control - c#

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

Related

Resizing and positioning panels in another panel

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);
}
}
}
}
}

Selected Filename not showing in Label from one Form to another C#

I am working modifying an application that will be an utility. The application is designed so far to load pictures from any folder and show them in thumbnails, then the user should be able to select those that will want to save in a database. The thumbnails consists of an ImageViewer form that will load each image. Thus, in the ImageViewer form there is a textbox and a checkbox. Each of them will be generated dynamically as many pictures are loaded (see the image below). The problem is that when clicking the checkbox it should show the name listed above the picture (thumbnail textbox) of the file in a label (it can be a label or textbox). Any time when the user clicks the checkbox will see a message saying: 'Added anyImage.jpg' or when deselecting the checkbox will say 'Removed anyImage.jpg'. It is not showing the text in the label. I have the following code.
This code is to load the main form:
public MainForm()
{
InitializeComponent();
Login loginSystem = new Login();
lbHowMany.Visible = false;
lbHowMany.Text = "Images";
lbNumberOfFiles.Visible = false;
btnEnableViewer.Text = "Disable Viewer";
this.buttonCancel.Enabled = false;
//stripSelectedFile.Text = "";
m_ImageDialog = new ImageDialog();
m_AddImageDelegate = new DelegateAddImage(this.AddImage);
m_Controller = new ThumbnailController();
m_Controller.OnStart += new ThumbnailControllerEventHandler(m_Controller_OnStart);
m_Controller.OnAdd += new ThumbnailControllerEventHandler(m_Controller_OnAdd);
m_Controller.OnEnd += new ThumbnailControllerEventHandler(m_Controller_OnEnd);
if (ImageViewer.sendSelectedFile != null)
{
stripSelectedFile.Text = ImageViewer.sendSelectedFile.ToString();
txInformation.Text = ImageViewer.sendSelectedFile.ToString();
}
}
This other code is from the ImageViewer form checkbox:
public void cboxToSave_CheckedChanged(object sender, EventArgs e)
{
if (cboxToSave.Checked == true)
{
sendSelectedFile = "Added: " + txFileName.Text;
}
else
{
{
sendSelectedFile = "Removed: " + txFileName.Text;
}
}
}
This is the variable declared in the class that will send the selected file name to the main form: public static string sendSelectedFile;
ImageViewer Code:
public partial class ImageViewer : UserControl
{
private Image m_Image;
private string m_ImageLocation;
private bool m_IsThumbnail;
private bool m_IsActive;
public static string sendSelectedFile;
public ImageViewer()
{
m_IsThumbnail = false;
m_IsActive = false;
InitializeComponent();
}
public Image Image
{
set
{
m_Image = value;
}
get
{
return m_Image;
}
}
public string ImageLocation
{
set
{
m_ImageLocation = value;
}
get
{
return m_ImageLocation;
}
}
public bool IsActive
{
set
{
m_IsActive = value;
this.Invalidate();
}
get
{
return m_IsActive;
}
}
public bool IsThumbnail
{
set
{
m_IsThumbnail = value;
}
get
{
return m_IsThumbnail;
}
}
public void ImageSizeChanged(object sender, ThumbnailImageEventArgs e)
{
this.Width = e.Size;
this.Height = e.Size;
this.Invalidate();
}
public void LoadImage(string imageFilename, int width, int height)
{
Image tempImage = Image.FromFile(imageFilename);
m_ImageLocation = imageFilename;
//gets the name of the file from the location
txFileName.Text = Path.GetFileNameWithoutExtension(imageFilename);
int dw = tempImage.Width;
int dh = tempImage.Height;
int tw = width;
int th = height;
double zw = (tw / (double)dw);
double zh = (th / (double)dh);
double z = (zw <= zh) ? zw : zh;
dw = (int)(dw * z);
dh = (int)(dh * z);
m_Image = new Bitmap(dw, dh);
Graphics g = Graphics.FromImage(m_Image);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(tempImage, 0, 0, dw, dh);
g.Dispose();
tempImage.Dispose();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
if (g == null) return;
if (m_Image == null) return;
int dw = m_Image.Width;
int dh = m_Image.Height;
int tw = this.Width - 8; // remove border, 4*4
int th = this.Height - 8; // remove border, 4*4
double zw = (tw / (double)dw);
double zh = (th / (double)dh);
double z = (zw <= zh) ? zw : zh;
dw = (int)(dw * z);
dh = (int)(dh * z);
int dl = 4 + (tw - dw) / 2; // add border 2*2
int dt = 4 + (th - dh) / 2; // add border 2*2
g.DrawRectangle(new Pen(Color.Yellow), dl, dt, dw, dh);
if (m_IsThumbnail)
for (int j = 0; j < 3; j++)
{
//draws and color the horizontal line in the miniature
g.DrawLine(new Pen(Color.LightSalmon),
new Point(dl + 3, dt + dh + 1 + j),
new Point(dl + dw + 3, dt + dh + 1 + j));
//draws and color the vertical right line in the miniature
g.DrawLine(new Pen(Color.LightGreen),
new Point(dl + dw + 1 + j, dt + 3),
new Point(dl + dw + 1 + j, dt + dh + 3));
}
g.DrawImage(m_Image, dl, dt, dw, dh);
if (m_IsActive)
{
//draws the rectangle inside and gives it color
g.DrawRectangle(new Pen(Color.MediumTurquoise, 1), dl, dt, dw, dh);
//draws the rectangle outside and gives it color
g.DrawRectangle(new Pen(Color.RosyBrown, 2), dl - 2, dt - 2, dw + 4, dh + 4);
}
}
private void OnResize(object sender, EventArgs e)
{
this.Invalidate();
}
public void cboxToSave_CheckedChanged(object sender, EventArgs e)
{
if (cboxToSave.Checked == true)
{
sendSelectedFile = "Added: " + txFileName.Text;
}
else
{
{
sendSelectedFile = "Removed: " + txFileName.Text;
}
}
}
}
Code in the MainForm that adds the images in the flowLayoutPanelMain
delegate void DelegateAddImage(string imageFilename);
private DelegateAddImage m_AddImageDelegate;
private void AddImage(string imageFilename)
{
try
{
// thread safe
if (this.InvokeRequired)
{
this.Invoke(m_AddImageDelegate, imageFilename);
}
else
{
int size = ImageSize;
lbNumberOfFiles.Visible = true;
lbHowMany.Visible = true;
ImageViewer imageViewer = new ImageViewer();
imageViewer.Dock = DockStyle.Bottom;
imageViewer.LoadImage(imageFilename, 256, 256);
imageViewer.Width = size;
imageViewer.Height = size;
imageViewer.IsThumbnail = true;
imageViewer.MouseClick += new MouseEventHandler(imageViewer_MouseClick);
txInformation.Text = imageFilename;
SetProgressBar();
counter++;
lbHowMany.Text = "Images";
lbNumberOfFiles.Text = counter.ToString();
this.OnImageSizeChanged += new ThumbnailImageEventHandler(imageViewer.ImageSizeChanged);
//passes the pictures to the main picture container
this.flowLayoutPanelMain.Controls.Add(imageViewer);
}
}
catch (Exception e)
{
MessageBox.Show("An error has ocurred. Error: " + e, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Here's a quick example of the ImageViewer Form raising a custom event whenever the checkbox is changed:
public partial class ImageViewer : Form
{
public ImageViewer()
{
InitializeComponent();
}
public delegate void dlgImageChecked(ImageViewer sender, string message);
public event dlgImageChecked ImageChecked;
private void cboxToSave_CheckedChanged(object sender, EventArgs e)
{
if (ImageChecked != null)
{
ImageChecked(this, (cboxToSave.Checked ? "Added: " : "Removed: ") + txFileName.Text);
}
}
}
Now, when you create instances of ImageViewer, you need to wire up that event...something like:
// ... in your MainForm class ...
private void button1_Click(object sender, EventArgs e)
{
// when you create your instances of ImageViewer, wire up their ImageChecked() event:
ImageViewer iv = new ImageViewer();
iv.ImageChecked += Iv_ImageChecked;
}
private void Iv_ImageChecked(ImageViewer sender, string message)
{
ImageViewer iv = (ImageViewer)sender; // if you need to reference it for other reasons ...
stripSelectedFile.Text = message;
txInformation.Text = message;
}
Your original post didn't show the creation of your ImageViewer instances so you'll need to incorporate the above somehow into your code.

c# New button class "infinite loop error"

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; //***
...
}

Detect if the TIFF image is Horizontal or Vertical - C#

Im using WinForms. In my Form i have a picturebox and a next button. I use this picturebox to display tiff images and i use the next button to navigate to the next page. The tiff documents are multipage images. The document I'm trying to view has a horizontal images and a vertical images like the example below. If its horizontal i want to size it (1100, 800), but if its vertical i want to size it (800, 1100). How do i do this? currently this is what i have but its not a good solution.
System.Drawing.Image img = System.Drawing.Image.FromFile(path_lbl.Text);
if (img.Height > img.Width)
{
pictureBox1.Width = 800;
pictureBox1.Height = 1300;
}
else
{
pictureBox1.Width = 1300;
pictureBox1.Height = 800;
}
I currently use this approach but this doesn't work because if the first image is vertical the if-statement will always execute the first condition pictureBox1.size(1300 , 800); With this method, if the next image is horizontal the condition will not ever re-size it horizontally.
Example Tiff image
http://www.filedropper.com/verticalandhorizontal
Quick Test Code
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace Demo
{
class TestForm : Form
{
public TestForm()
{
var panel = new Panel { Dock = DockStyle.Top, BorderStyle = BorderStyle.FixedSingle };
openButton = new Button { Text = "Open", Top = 8, Left = 16 };
prevButton = new Button { Text = "Prev", Top = 8, Left = 16 + openButton.Right };
nextButton = new Button { Text = "Next", Top = 8, Left = 16 + prevButton.Right };
path_lbl = new Label { Text = "", Top = 12, Left = 16 + nextButton.Right };
panel.Height = 16 + openButton.Height;
panel.Controls.AddRange(new Control[] { openButton, prevButton, nextButton, path_lbl });
pageViewer = new PictureBox { Dock = DockStyle.Fill, SizeMode = PictureBoxSizeMode.Zoom };
ClientSize = new Size(850, 1100 + panel.Height);
Controls.AddRange(new Control[] { panel, pageViewer });
openButton.Click += OnOpenButtonClick;
prevButton.Click += OnPrevButtonClick;
nextButton.Click += OnNextButtonClick;
Disposed += OnFormDisposed;
UpdatePageInfo();
}
private Button openButton;
private Button prevButton;
private Button nextButton;
private PictureBox pageViewer;
private PageBuffer pageData;
private int currentPage;
private Size pageSize;
public string path;
private Label path_lbl;
private void OnOpenButtonClick(object sender, EventArgs e)
{
using (var dialog = new OpenFileDialog())
{
if (dialog.ShowDialog(this) == DialogResult.OK)
Open(dialog.FileName);
path = dialog.FileName;
}
}
private void OnPrevButtonClick(object sender, EventArgs e)
{
SelectPage(currentPage - 1);
}
private void OnNextButtonClick(object sender, EventArgs e)
{
//var data = PageBuffer.Open(path,Size= new Size(850,1150));
SelectPage(currentPage + 1);
//Debug.WriteLine("Current Size: 1300, 800");
}
private void OnFormDisposed(object sender, EventArgs e)
{
if (pageData != null)
pageData.Dispose();
}
private void Open(string path)
{
var data = PageBuffer.Open(path, new Size(1500, 1500));
pageViewer.Image = null;
if (pageData != null)
pageData.Dispose();
pageData = data;
SelectPage(0);
}
private void SelectPage(int index)
{
pageViewer.Image = pageData.GetPage(index);
currentPage = index;
UpdatePageInfo();
}
private void UpdatePageInfo()
{
prevButton.Enabled = pageData != null && currentPage > 0;
nextButton.Enabled = pageData != null && currentPage < pageData.PageCount - 1;
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TestForm());
}
}
class PageBuffer : IDisposable
{
public const int DefaultCacheSize = 12; //This is how much images it will have in memory
public static PageBuffer Open(string path, Size maxSize, int cacheSize = DefaultCacheSize)
{
return new PageBuffer(File.OpenRead(path), maxSize, cacheSize);
}
private PageBuffer(Stream stream, Size maxSize, int cacheSize)
{
this.stream = stream;
source = Image.FromStream(stream);
pageCount = source.GetFrameCount(FrameDimension.Page);
if (pageCount < 2) return;
pageCache = new Image[Math.Min(pageCount, Math.Max(cacheSize, 5))];
pageSize = source.Size;
if (!maxSize.IsEmpty)
{
float scale = Math.Min((float)maxSize.Width / pageSize.Width, (float)maxSize.Height / pageSize.Height);
pageSize = new Size((int)(pageSize.Width * scale), (int)(pageSize.Height * scale));
}
var worker = new Thread(LoadPages) { IsBackground = true };
worker.Start();
}
private void LoadPages()
{
while (true)
{
lock (syncLock)
{
if (disposed) return;
int index = Array.FindIndex(pageCache, 0, pageCacheSize, p => p == null);
if (index < 0)
Monitor.Wait(syncLock);
else
pageCache[index] = LoadPage(pageCacheStart + index);
}
}
}
private Image LoadPage(int index)
{
source.SelectActiveFrame(FrameDimension.Page, index);
return new Bitmap(source, pageSize);
}
private Stream stream;
private Image source;
private int pageCount;
private Image[] pageCache;
private int pageCacheStart, pageCacheSize;
private object syncLock = new object();
private bool disposed;
private Size pageSize;
public Image Source { get { return source; } }
public int PageCount { get { return pageCount; } }
public Image GetPage(int index)
{
if (disposed) throw new ObjectDisposedException(GetType().Name);
if (PageCount < 2) return Source;
lock (syncLock)
{
AdjustPageCache(index);
int cacheIndex = index - pageCacheStart;
var image = pageCache[cacheIndex];
if (image == null)
image = pageCache[cacheIndex] = LoadPage(index);
return image;
}
}
private void AdjustPageCache(int pageIndex)
{
int start, end;
if ((start = pageIndex - pageCache.Length / 2) <= 0)
end = (start = 0) + pageCache.Length;
else if ((end = start + pageCache.Length) >= PageCount)
start = (end = PageCount) - pageCache.Length;
if (start < pageCacheStart)
{
int shift = pageCacheStart - start;
if (shift >= pageCacheSize)
ClearPageCache(0, pageCacheSize);
else
{
ClearPageCache(pageCacheSize - shift, pageCacheSize);
for (int j = pageCacheSize - 1, i = j - shift; i >= 0; j--, i--)
Exchange(ref pageCache[i], ref pageCache[j]);
}
}
else if (start > pageCacheStart)
{
int shift = start - pageCacheStart;
if (shift >= pageCacheSize)
ClearPageCache(0, pageCacheSize);
else
{
ClearPageCache(0, shift);
for (int j = 0, i = shift; i < pageCacheSize; j++, i++)
Exchange(ref pageCache[i], ref pageCache[j]);
}
}
if (pageCacheStart != start || pageCacheStart + pageCacheSize != end)
{
pageCacheStart = start;
pageCacheSize = end - start;
Monitor.Pulse(syncLock);
}
}
void ClearPageCache(int start, int end)
{
for (int i = start; i < end; i++)
Dispose(ref pageCache[i]);
}
static void Dispose<T>(ref T target) where T : class, IDisposable
{
var value = target;
if (value != null) value.Dispose();
target = null;
}
static void Exchange<T>(ref T a, ref T b) { var c = a; a = b; b = c; }
public void Dispose()
{
if (disposed) return;
lock (syncLock)
{
disposed = true;
if (pageCache != null)
{
ClearPageCache(0, pageCacheSize);
pageCache = null;
}
Dispose(ref source);
Dispose(ref stream);
if (pageCount > 2)
Monitor.Pulse(syncLock);
}
}
}
}

Most Efficient way to do a swipe animation in Xamarin.forms - Android

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; }
}
}

Categories