Implemented Editable Cells from gtk3-demo
This commit is contained in:
parent
e82b07ede1
commit
1add3d8868
1 changed files with 291 additions and 0 deletions
291
Source/Samples/Sections/Widgets/EditableCellsSection.cs
Normal file
291
Source/Samples/Sections/Widgets/EditableCellsSection.cs
Normal file
|
@ -0,0 +1,291 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Gtk;
|
||||
|
||||
namespace Samples.Sections.Widgets
|
||||
{
|
||||
[Section(ContentType = typeof(EditableCellsSection), Category = Category.Widgets)]
|
||||
class EditableCellsSection : Box
|
||||
{
|
||||
private readonly TreeView _treeView;
|
||||
private readonly ListStore _itemsModel;
|
||||
private readonly Dictionary<CellRenderer, int> _cellColumnsRender;
|
||||
private List<Item> _articles;
|
||||
|
||||
public EditableCellsSection() : base(Orientation.Vertical, 3)
|
||||
{
|
||||
_cellColumnsRender = new Dictionary<CellRenderer, int>();
|
||||
ListStore numbers_model;
|
||||
|
||||
ScrolledWindow sw = new ScrolledWindow
|
||||
{
|
||||
ShadowType = ShadowType.EtchedIn
|
||||
};
|
||||
sw.SetPolicy(PolicyType.Automatic, PolicyType.Automatic);
|
||||
|
||||
this.PackStart(sw, true, true, 0);
|
||||
|
||||
/* create models */
|
||||
_itemsModel = CreateItemsModel();
|
||||
numbers_model = CreateNumbersModel();
|
||||
|
||||
/* create tree view */
|
||||
_treeView = new TreeView(_itemsModel);
|
||||
_treeView.Selection.Mode = SelectionMode.Single;
|
||||
|
||||
AddColumns(numbers_model);
|
||||
|
||||
sw.Add(_treeView);
|
||||
|
||||
/* some buttons */
|
||||
Box hbox = new Box(Orientation.Horizontal, 4)
|
||||
{
|
||||
Homogeneous = true
|
||||
};
|
||||
this.PackStart(hbox, false, false, 0);
|
||||
|
||||
Button button = new Button("Add item");
|
||||
button.Clicked += AddItem;
|
||||
hbox.PackStart(button, true, true, 0);
|
||||
|
||||
button = new Button("Remove item");
|
||||
button.Clicked += RemoveItem;
|
||||
hbox.PackStart(button, true, true, 0);
|
||||
}
|
||||
|
||||
private class Item
|
||||
{
|
||||
public int Number;
|
||||
public string Product;
|
||||
public int Yummy;
|
||||
}
|
||||
|
||||
private enum ColumnItem
|
||||
{
|
||||
Number,
|
||||
Product,
|
||||
Yummy,
|
||||
Num
|
||||
};
|
||||
|
||||
private enum ColumnNumber
|
||||
{
|
||||
Text,
|
||||
Num
|
||||
};
|
||||
|
||||
private ListStore CreateItemsModel()
|
||||
{
|
||||
ListStore model;
|
||||
TreeIter iter;
|
||||
|
||||
/* create array */
|
||||
_articles = new List<Item>();
|
||||
|
||||
AddItems();
|
||||
|
||||
/* create list store */
|
||||
model = new ListStore(typeof(int), typeof(string), typeof(int), typeof(bool));
|
||||
|
||||
/* add items */
|
||||
for (int i = 0; i < _articles.Count; i++)
|
||||
{
|
||||
iter = model.Append();
|
||||
model.SetValue(iter, (int)ColumnItem.Number, _articles[i].Number);
|
||||
model.SetValue(iter, (int)ColumnItem.Product, _articles[i].Product);
|
||||
model.SetValue(iter, (int)ColumnItem.Yummy, _articles[i].Yummy);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private static ListStore CreateNumbersModel()
|
||||
{
|
||||
ListStore model;
|
||||
TreeIter iter;
|
||||
|
||||
/* create list store */
|
||||
model = new ListStore(typeof(string), typeof(int));
|
||||
|
||||
/* add numbers */
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
iter = model.Append();
|
||||
model.SetValue(iter, (int)ColumnNumber.Text, i.ToString());
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
private void AddItems()
|
||||
{
|
||||
Item foo = new Item
|
||||
{
|
||||
Number = 3,
|
||||
Product = "bottles of coke",
|
||||
Yummy = 20
|
||||
};
|
||||
_articles.Add(foo);
|
||||
|
||||
foo = new Item
|
||||
{
|
||||
Number = 5,
|
||||
Product = "packages of noodles",
|
||||
Yummy = 50
|
||||
};
|
||||
_articles.Add(foo);
|
||||
|
||||
foo = new Item
|
||||
{
|
||||
Number = 2,
|
||||
Product = "packages of chocolate chip cookies",
|
||||
Yummy = 90
|
||||
};
|
||||
_articles.Add(foo);
|
||||
|
||||
foo = new Item
|
||||
{
|
||||
Number = 1,
|
||||
Product = "can vanilla ice cream",
|
||||
Yummy = 60
|
||||
};
|
||||
_articles.Add(foo);
|
||||
|
||||
foo = new Item
|
||||
{
|
||||
Number = 6,
|
||||
Product = "eggs",
|
||||
Yummy = 10
|
||||
};
|
||||
_articles.Add(foo);
|
||||
}
|
||||
|
||||
private void AddColumns(ITreeModel numbersModel)
|
||||
{
|
||||
/* number column */
|
||||
CellRendererCombo rendererCombo = new CellRendererCombo
|
||||
{
|
||||
Model = numbersModel,
|
||||
TextColumn = (int)ColumnNumber.Text,
|
||||
HasEntry = false,
|
||||
Editable = true
|
||||
};
|
||||
rendererCombo.Edited += CellEdited;
|
||||
rendererCombo.EditingStarted += EditingStarted;
|
||||
_cellColumnsRender.Add(rendererCombo, (int)ColumnItem.Number);
|
||||
|
||||
_treeView.InsertColumn(-1, "Number", rendererCombo, "text", (int)ColumnItem.Number);
|
||||
|
||||
/* product column */
|
||||
CellRendererText rendererText = new CellRendererText
|
||||
{
|
||||
Editable = true
|
||||
};
|
||||
rendererText.Edited += CellEdited;
|
||||
_cellColumnsRender.Add(rendererText, (int)ColumnItem.Product);
|
||||
|
||||
_treeView.InsertColumn(-1, "Product", rendererText, "text", (int)ColumnItem.Product);
|
||||
|
||||
/* yummy column */
|
||||
CellRendererProgress rendererProgress = new CellRendererProgress();
|
||||
_cellColumnsRender.Add(rendererProgress, (int)ColumnItem.Yummy);
|
||||
|
||||
_treeView.InsertColumn(-1, "Yummy", rendererProgress, "value", (int)ColumnItem.Yummy);
|
||||
}
|
||||
|
||||
private void AddItem(object sender, EventArgs e)
|
||||
{
|
||||
TreeIter iter;
|
||||
|
||||
if (_articles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Item foo = new Item
|
||||
{
|
||||
Number = 0,
|
||||
Product = "Description here",
|
||||
Yummy = 50
|
||||
};
|
||||
_articles.Add(foo);
|
||||
|
||||
/* Insert a new row below the current one */
|
||||
_treeView.GetCursor(out TreePath path, out _);
|
||||
if (path != null)
|
||||
{
|
||||
_ = _itemsModel.GetIter(out TreeIter current, path);
|
||||
iter = _itemsModel.InsertAfter(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter = _itemsModel.Insert(-1);
|
||||
}
|
||||
|
||||
/* Set the data for the new row */
|
||||
_itemsModel.SetValue(iter, (int)ColumnItem.Number, foo.Number);
|
||||
_itemsModel.SetValue(iter, (int)ColumnItem.Product, foo.Product);
|
||||
_itemsModel.SetValue(iter, (int)ColumnItem.Yummy, foo.Yummy);
|
||||
|
||||
/* Move focus to the new row */
|
||||
path = _itemsModel.GetPath(iter);
|
||||
TreeViewColumn column = _treeView.GetColumn(0);
|
||||
_treeView.SetCursor(path, column, false);
|
||||
}
|
||||
|
||||
private void RemoveItem(object sender, EventArgs e)
|
||||
{
|
||||
TreeSelection selection = _treeView.Selection;
|
||||
|
||||
if (selection.GetSelected(out TreeIter iter))
|
||||
{
|
||||
TreePath path = _itemsModel.GetPath(iter);
|
||||
int i = path.Indices[0];
|
||||
_itemsModel.Remove(ref iter);
|
||||
_articles.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void CellEdited(object data, EditedArgs args)
|
||||
{
|
||||
TreePath path = new TreePath(args.Path);
|
||||
int column = _cellColumnsRender[(CellRenderer)data];
|
||||
_itemsModel.GetIter(out TreeIter iter, path);
|
||||
|
||||
switch (column)
|
||||
{
|
||||
case (int)ColumnItem.Number:
|
||||
{
|
||||
int i = path.Indices[0];
|
||||
_articles[i].Number = int.Parse(args.NewText);
|
||||
|
||||
_itemsModel.SetValue(iter, column, _articles[i].Number);
|
||||
}
|
||||
break;
|
||||
|
||||
case (int)ColumnItem.Product:
|
||||
{
|
||||
string oldText = (string)_itemsModel.GetValue(iter, column);
|
||||
int i = path.Indices[0];
|
||||
_articles[i].Product = args.NewText;
|
||||
|
||||
_itemsModel.SetValue(iter, column, _articles[i].Product);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void EditingStarted(object o, EditingStartedArgs args)
|
||||
{
|
||||
((ComboBox)args.Editable).RowSeparatorFunc += SeparatorRow;
|
||||
}
|
||||
|
||||
private bool SeparatorRow(ITreeModel model, TreeIter iter)
|
||||
{
|
||||
TreePath path = model.GetPath(iter);
|
||||
int idx = path.Indices[0];
|
||||
|
||||
return idx == 5;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue