Skip to content

Instantly share code, notes, and snippets.

@cwensley
Created May 6, 2016 18:18
Show Gist options
  • Save cwensley/cb23b0bfa2a2df6588e341f5800e67ad to your computer and use it in GitHub Desktop.
Save cwensley/cb23b0bfa2a2df6588e341f5800e67ad to your computer and use it in GitHub Desktop.
Shows how to create an icon grid layout control in Eto.Forms
using System;
using System.Collections.ObjectModel;
using Eto.Forms;
using Eto.Drawing;
namespace Examples
{
public class IconGridLayout : Panel
{
int? lastWidth;
PixelLayout layout;
class IconCollection : Collection<Control>
{
public IconGridLayout Parent { get; set; }
protected override void InsertItem(int index, Control item)
{
base.InsertItem(index, item);
Parent.layout.Add(item, 0, 0);
Parent.Layout(false);
}
protected override void RemoveItem(int index)
{
var item = this[index];
base.RemoveItem(index);
Parent.layout.Remove(item);
Parent.Layout(false);
}
protected override void ClearItems()
{
Parent.layout.RemoveAll();
base.ClearItems();
Parent.Layout(false);
}
protected override void SetItem(int index, Control item)
{
var old = this[index];
Parent.layout.Remove(old);
base.SetItem(index, item);
Parent.layout.Add(item, 0, 0);
Parent.Layout(false);
}
}
public Size ItemSize { get; set; } = new Size(64, 64);
public Padding ItemPadding { get; set; } = new Padding(8);
public Collection<Control> Items { get; }
public IconGridLayout()
{
layout = new PixelLayout();
Content = layout;
Items = new IconCollection { Parent = this };
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Layout(true);
}
void Layout(bool force)
{
if (!(force || Loaded))
return;
layout.SuspendLayout();
var location = new Point(0, 0);
var itemSize = ItemSize + ItemPadding.Size;
var topLeft = new Point(ItemPadding.Left, ItemPadding.Top);
var size = Size;
foreach (var item in Items) {
item.Size = ItemSize;
if (location.X + itemSize.Width > size.Width) {
location.X = 0;
location.Y += itemSize.Height;
}
layout.Move(item, location + topLeft);
location.X += itemSize.Width;
}
if (Items.Count > 0)
location.Y += itemSize.Height;
MinimumSize = new Size(MinimumSize.Width, location.Y);
layout.ResumeLayout();
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
var newWidth = Width / (ItemSize.Width + ItemPadding.Horizontal);
if (lastWidth != newWidth) {
// only re-jig when width changes
lastWidth = newWidth;
Application.Instance.AsyncInvoke(() => Layout(true));
}
}
}
}
using System;
using Eto.Forms;
using Eto.Drawing;
namespace Examples
{
public class IconItem : StackLayout
{
readonly ImageView imageView;
readonly Label label;
public string Text
{
get { return label.Text; }
set { label.Text = value; }
}
public Image Image
{
get { return imageView.Image; }
set { imageView.Image = value; }
}
public IconItem()
{
Spacing = 2;
imageView = new ImageView(); // { Size = new Size(24, 24) };
HorizontalContentAlignment = HorizontalAlignment.Stretch;
label = new Label();
label.TextAlignment = TextAlignment.Center;
Items.Add(new StackLayoutItem(imageView, HorizontalAlignment.Center, false));
Items.Add(new StackLayoutItem(label, true));
}
}
}
Copy link

ghost commented Jan 8, 2017

You would really add this to Eto.Forms... Since it is so useful...

Also, may I use this in my code?

@cwensley
Copy link
Author

cwensley commented Aug 8, 2017

@ghost: yes, it would be nice in Eto.Forms. It'd need to be a bit more flushed out and possibly implemented per platform. Additional things to add would be selection and drag/drop.

And yes, anyone may use this (or any of my gists).

(btw, sorry for the late response, I didn't actually see your note until I came back to this to refer someone else to it)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment