no more submodule

This commit is contained in:
2024-09-15 22:40:48 +02:00
parent df3b8a3135
commit 0234b33671
5804 changed files with 943618 additions and 1 deletions

View File

@@ -0,0 +1,12 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
namespace Samples
{
enum Category
{
Widgets,
Dialogs,
Miscellaneous
}
}

View File

@@ -0,0 +1,17 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(AboutDialog), Category = Category.Dialogs)]
class AboutDialogSection : Box
{
public AboutDialogSection() : base(Orientation.Vertical, 0)
{
}
}
}

View File

@@ -0,0 +1,32 @@
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(FileChooserDialog), Category = Category.Dialogs)]
class FileChooserDialogSection : ListSection
{
public FileChooserDialogSection ()
{
AddItem ($"Press button to open {nameof(FileChooserDialog)} :", new FileChooserDialogDemo ("Press me"));
}
}
class FileChooserDialogDemo : Button
{
public FileChooserDialogDemo (string text) : base (text) { }
protected override void OnPressed ()
{
var fcd = new FileChooserDialog ("Open File", null, FileChooserAction.Open);
fcd.AddButton (Stock.Cancel, ResponseType.Cancel);
fcd.AddButton (Stock.Open, ResponseType.Ok);
fcd.DefaultResponse = ResponseType.Ok;
fcd.SelectMultiple = false;
ResponseType response = (ResponseType) fcd.Run ();
if (response == ResponseType.Ok)
ApplicationOutput.WriteLine (fcd.Filename);
fcd.Destroy ();
}
}
}

View File

@@ -0,0 +1,49 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using System;
using Gtk;
namespace Samples
{
public class ListSection : Box
{
private Grid _grid;
private int _position;
public ListSection() : base(Orientation.Vertical, 0)
{
_position = 0;
_grid = new Grid
{
RowSpacing = 6,
ColumnSpacing = 6
};
PackStart(_grid, false, true, 0);
PackStart(new VBox(), true, true, 0);
}
public void AddItem((string, Widget) turp)
{
AddItem(turp.Item1, turp.Item2);
}
public void AddItem(string label, Widget widget)
{
_grid.Attach(new Label
{
Text = label,
Hexpand = true,
Halign = Align.Start
}, 0, _position, 1, 1);
var hbox = new HBox();
hbox.PackStart(new VBox(), true, true, 0);
hbox.PackStart(widget, false, true, 0);
_grid.Attach(hbox, 1, _position, 1, 1);
_position++;
}
}
}

View File

@@ -0,0 +1,147 @@
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(ContainerChildProperties), Category = Category.Miscellaneous)]
class ContainerChildPropertiesSection : Box
{
public ContainerChildPropertiesSection() : base(Orientation.Vertical, 3)
{
ContainerChildProperties.CreateBoxProperties(this);
ContainerChildProperties.CreateGridProperties(this);
ContainerChildProperties.CreateStackProperties(this);
}
}
static class ContainerChildProperties
{
public static void CreateBoxProperties(Box parent)
{
var title = new Label { Text = "Box child properties" };
parent.PackStart(title, false, true, 0);
var box1 = new Box(Orientation.Horizontal, 3);
var btn1 = new Button() { Label = "Expand" };
btn1.Clicked += delegate
{
var child = (Box.BoxChild)box1[btn1];
child.Expand = !child.Expand;
ApplicationOutput.WriteLine(child, "Expand changed to " + child.Expand);
};
box1.PackStart(btn1, true, true, 0);
parent.PackStart(box1, false, true, 0);
var box2 = new Box(Orientation.Horizontal, 3);
var btn2 = new Button() { Label = "PackType" };
btn2.Clicked += delegate
{
var child = (Box.BoxChild)box2[btn2];
child.PackType = child.PackType == PackType.Start ? PackType.End : PackType.Start;
ApplicationOutput.WriteLine(child, "PackType changed to " + child.PackType);
};
box2.PackStart(btn2, false, false, 0);
parent.PackStart(box2, false, true, 0);
var box3 = new Box(Orientation.Horizontal, 3);
var btn3 = new Button() { Label = "Position" };
btn3.Clicked += delegate
{
var child = (Box.BoxChild)box3[btn3];
child.Position = child.Position == 0 ? 1 : 0;
ApplicationOutput.WriteLine(child, "Position changed to " + child.Position);
};
box3.PackStart(btn3, false, false, 0);
box3.PackStart(new Label { Text = "Neighbor" }, false, false, 0);
parent.PackStart(box3, false, true, 0);
}
public static void CreateGridProperties(Box parent)
{
var title = new Label { Text = "Grid child properties" };
parent.PackStart(title, false, true, 0);
var grid = new Grid { ColumnSpacing = 3, RowSpacing = 3 };
var btn1 = new Button { Label = "LeftAttach" };
var lbl = new Label { Text = "Neighbor" };
btn1.Clicked += delegate
{
var child1 = (Grid.GridChild)grid[btn1];
var child2 = (Grid.GridChild)grid[lbl];
if (child1.LeftAttach == 0)
{
child1.LeftAttach = 1;
child2.LeftAttach = 0;
}
else
{
child1.LeftAttach = 0;
child2.LeftAttach = 1;
}
ApplicationOutput.WriteLine(child1, "Child 1 LeftAttach changed to " + child1.LeftAttach);
ApplicationOutput.WriteLine(child1, "Child 2 LeftAttach changed to " + child2.LeftAttach);
};
var btn2 = new Button { Label = "Width (column span)", Hexpand = true };
btn2.Clicked += delegate
{
var child = (Grid.GridChild)grid[btn2];
child.Width = child.Width == 1 ? 2 : 1;
ApplicationOutput.WriteLine(child, "Width changed to " + child.Width);
};
grid.Attach(btn1, 0, 0, 1, 1);
grid.Attach(lbl, 1, 0, 1, 1);
grid.Attach(btn2, 0, 1, 1, 1);
parent.PackStart(grid, false, true, 0);
}
public static void CreateStackProperties(Box parent)
{
var title = new Label { Text = "Stack child properties" };
parent.PackStart(title, false, true, 0);
var stack = new Stack();
var box = new Box(Orientation.Horizontal, 3);
var btn1 = new Button { Label = "Title" };
btn1.Clicked += delegate
{
var child = (Stack.StackChild)stack[box];
child.Title = child.Title == "Page 1" ? "Page 1 abc" : "Page 1";
ApplicationOutput.WriteLine(child, "Title changed to " + child.Title);
};
box.PackStart(btn1, false, false, 0);
var btn2 = new Button { Label = "Position" };
var lbl = new Label { Text = "Page 2 label", Halign = Align.Start };
btn2.Clicked += delegate
{
var child1 = (Stack.StackChild)stack[box];
var child2 = (Stack.StackChild)stack[lbl];
if (child1.Position == 0)
{
child1.Position = 1;
child2.Position = 0;
}
else
{
child1.Position = 0;
child2.Position = 1;
}
ApplicationOutput.WriteLine(child1, "Child 1 Position changed to " + child1.Position);
ApplicationOutput.WriteLine(child1, "Child 2 Position changed to " + child2.Position);
};
box.PackStart(btn2, false, false, 0);
stack.AddTitled(box, "1", "Page 1");
stack.AddTitled(lbl, "2", "Page 2");
var switcher = new StackSwitcher();
switcher.Stack = stack;
parent.PackStart(switcher, false, true, 0);
parent.PackStart(stack, false, true, 0);
}
}
}

View File

@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(CssNameDemo), Category = Category.Miscellaneous)]
class CssNameSection : Box
{
public CssNameSection() : base(Orientation.Vertical, 3)
{
CssNameDemo.Create(this);
}
}
class CssNameDemo
{
// inherited label has same css name as parent
internal class MyLabel : Label
{
}
// css name can be set by [CssName]
[CssName("my-label-attrib")]
internal class MyLabelWithAttrib : Label
{
}
// css name can be set in class initializer method
[GLib.TypeInitializer(typeof(MyLabelWithInit), nameof(MyLabelWithInit.ClassInit))]
internal class MyLabelWithInit : Label
{
static void ClassInit(GLib.GType gtype, Type type)
{
SetCssName(gtype, "my-label-init");
}
}
public static void Create(Box box)
{
var css = new CssProvider();
css.LoadFromData(@"
label.x {
background: LightCoral;
}
my-label-attrib {
background: LightGreen;
}
my-label-init {
background: LightSkyBlue;
}
my-label-init.x {
background: LightBlue;
}
");
StyleContext.AddProviderForScreen(Gdk.Screen.Default, css, StyleProviderPriority.Application);
string name;
name = Widget.GetCssName(Label.GType);
var label1 = new Label { Text = "Label, css name: " + name };
label1.StyleContext.AddClass("x");
name = Widget.GetCssName((GLib.GType)typeof(MyLabel));
var label2 = new MyLabel { Text = "Inherited Label, css name: " + name };
label2.StyleContext.AddClass("x");
name = Widget.GetCssName((GLib.GType)typeof(MyLabelWithAttrib));
var label3 = new MyLabelWithAttrib { Text = "Inherited Label with [CssName], css name: " + name };
name = Widget.GetCssName((GLib.GType)typeof(MyLabelWithInit));
var label4 = new MyLabelWithInit { Text = "Inherited Label with class initializer, css name: " + name };
name = Widget.GetCssName((GLib.GType)typeof(MyLabelWithInit));
var label5 = new MyLabelWithInit { Text = "Inherited Label with class initializer and css class, css name: " + name };
label5.StyleContext.AddClass("x");
box.PackStart(label1, false, false, 0);
box.PackStart(label2, false, false, 0);
box.PackStart(label3, false, false, 0);
box.PackStart(label4, false, false, 0);
box.PackStart(label5, false, false, 0);
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(MonitorDemo), Category = Category.Miscellaneous)]
class MonitorSection : ListSection
{
public MonitorSection()
{
AddItem("Press button to get monitors information:", new MonitorDemo("Press me"));
}
}
class MonitorDemo : Button
{
public MonitorDemo(string text) : base(text)
{
}
protected override void OnPressed()
{
base.OnPressed();
Gdk.Display display = Gdk.Display.Default;
int monitorsCount = display.NMonitors;
ApplicationOutput.WriteLine($"Monitors count: {monitorsCount}");
for (int i = 0; i < monitorsCount; i++)
{
Gdk.Monitor monitor = display.GetMonitor(i);
ApplicationOutput.WriteLine($"Monitor {i}:");
ApplicationOutput.WriteLine($"\tIsPrimary: {monitor.IsPrimary}");
ApplicationOutput.WriteLine($"\tManufacturer: {monitor.Manufacturer}");
ApplicationOutput.WriteLine($"\tModel: {monitor.Model}");
ApplicationOutput.WriteLine($"\tRefreshRate: {monitor.RefreshRate}");
ApplicationOutput.WriteLine($"\tScaleFactor: {monitor.ScaleFactor}");
ApplicationOutput.WriteLine($"\tWidthMm x HeightMm: {monitor.WidthMm} x {monitor.HeightMm}");
ApplicationOutput.WriteLine($"\tGeometry: {monitor.Geometry}");
ApplicationOutput.WriteLine($"\tWorkarea: {monitor.Workarea}");
}
}
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.IO;
using System.Threading;
using Gdk;
using Gtk;
namespace Samples
{
[Section (ContentType = typeof(PixbufDemo), Category = Category.Miscellaneous)]
class PixbufSection : ListSection
{
public PixbufSection ()
{
AddItem ($"Press button to run / stop {nameof(PixbufDemo)} :", new PixbufDemo ("Press me"));
}
}
class PixbufDemo : Button
{
public PixbufDemo (string text) : base (text) { }
private bool running = false;
public void DispatchPendingEvents ()
{
// The loop is limited to 1000 iterations as a workaround for an issue that some users
// have experienced. Sometimes EventsPending starts return 'true' for all iterations,
// causing the loop to never end.
int n = 1000;
Gdk.Threads.Enter ();
while (Gtk.Application.EventsPending () && --n > 0) {
Gtk.Application.RunIteration (false);
}
Gdk.Threads.Leave ();
}
protected override void OnPressed ()
{
base.OnPressed ();
var count = 0;
if (running) {
running = false;
return;
}
var startmem = GC.GetTotalMemory (true);
var testfile = "Textpic.png";
using var teststream = typeof(ImageSection).Assembly.GetManifestResourceStream("Testpic");
using (var writeTestFile = new FileStream(testfile, FileMode.Create)) {
teststream.CopyTo(writeTestFile);
}
using (var heatup = new Pixbuf (testfile)) {
ApplicationOutput.WriteLine ($"{nameof(heatup)}.{nameof(Pixbuf.ByteLength)}\t{heatup.ByteLength:N0}");
}
startmem = GC.GetTotalMemory (true);
ApplicationOutput.WriteLine ($"{nameof(GC.GetTotalMemory)} at start: {startmem:N}");
running = true;
var memAllocated = 0UL;
while (running) {
using (var source = new Pixbuf (typeof(ImageSection).Assembly, "Testpic")) {
memAllocated += source.ByteLength;
count++;
}
DispatchPendingEvents ();
if (!running)
break;
}
var endmem = GC.GetTotalMemory (true);
ApplicationOutput.WriteLine ($"Leak:\t{(endmem - startmem):N0}\t{nameof(memAllocated)}");
ApplicationOutput.WriteLine ($"{nameof(GC.GetTotalMemory)} at start: {startmem:N0}\tat end: {endmem:N0}\t{nameof(Pixbuf)} created: {count}");
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(PolarFixed), Category = Category.Miscellaneous)]
class PolarFixedSection : ListSection
{
public PolarFixedSection()
{
AddItem(CreateClock());
AddItem(CreateSpiral());
}
public (string, Widget) CreateClock()
{
double theta;
// Clock
PolarFixed pf = new PolarFixed();
for (int hour = 1; hour <= 12; hour++)
{
theta = (Math.PI / 2) - hour * (Math.PI / 6);
if (theta < 0)
theta += 2 * Math.PI;
Label l = new Label("<big><b>" + hour.ToString() + "</b></big>");
l.UseMarkup = true;
pf.Put(l, theta, 50);
}
return ("Clock", pf);
}
public (string, Widget) CreateSpiral()
{
uint r;
double theta;
var pf = new PolarFixed();
r = 0;
theta = 0.0;
foreach (string id in Gtk.Stock.ListIds())
{
StockItem item = Gtk.Stock.Lookup(id);
if (item.Label == null)
continue;
var icon = Gtk.Image.NewFromIconName(item.StockId, IconSize.SmallToolbar);
pf.Put(icon, theta, r);
// Logarithmic spiral: r = a*e^(b*theta)
r += 1;
theta = 10 * Math.Log(10 * r);
}
return ("Spiral", pf);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using Gtk;
namespace Samples
{
[Section(ContentType=typeof(SeatDemo), Category = Category.Miscellaneous)]
class SeatSection : ListSection
{
public SeatSection()
{
AddItem("Press button to output mouse location:", new SeatDemo("Press me"));
}
}
class SeatDemo : Button
{
public SeatDemo(string text) : base(text)
{
}
protected override void OnPressed()
{
base.OnPressed();
var seat = Display.DefaultSeat;
ApplicationOutput.WriteLine($"Default seat: {seat}");
seat.Pointer.GetPosition(null, out int x, out int y);
ApplicationOutput.WriteLine($"Position: ({x}, {y})");
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(StyleContext), Category = Category.Miscellaneous)]
class StyleContextSection : ListSection
{
public StyleContextSection()
{
var btn = new Button() { Label = "Press me" };
btn.Clicked += OnBtnClicked;
AddItem("Press button to output style context properties:", btn);
}
private void OnBtnClicked(object sender, EventArgs e)
{
var styleCtx = ((Button)sender).StyleContext;
var props = new[] { "padding-left", "padding-right", "padding-top", "padding-bottom", "min-width", "min-height", "color", "background-color", "font-size", "font-style" };
foreach (var prop in props)
{
GLib.Value val = styleCtx.GetProperty(prop, styleCtx.State);
string msg = string.Format("Property {0}, type {1}, value {2}", prop, val.Val.GetType().Name, val.Val.ToString());
ApplicationOutput.WriteLine(msg);
}
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(TimerDemo), Category = Category.Miscellaneous)]
class TimerSection : Box
{
public TimerSection() : base(Orientation.Horizontal, 3)
{
Valign = Align.Start;
TimerDemo.Create(this);
}
}
static class TimerDemo
{
public static void Create(Box box)
{
List<uint> timers = new List<uint>();
bool removeByHandler = false;
var btnAddTimer = new Button() { Label = "Add timer" };
btnAddTimer.Clicked += delegate
{
uint id = 0;
id = GLib.Timeout.Add(500, () =>
{
ApplicationOutput.WriteLine("Timer tick " + id);
if (removeByHandler)
{
removeByHandler = false;
timers.Remove(id);
ApplicationOutput.WriteLine("Remove timer from handler " + id);
return false;
}
return true;
});
timers.Add(id);
ApplicationOutput.WriteLine("Add timer " + id);
};
var btnRemoveTimer = new Button() { Label = "Remove timer" };
btnRemoveTimer.Clicked += delegate
{
if (timers.Count == 0)
return;
uint id = timers[0];
timers.RemoveAt(0);
GLib.Timeout.Remove(id);
ApplicationOutput.WriteLine("Remove timer " + id);
};
var btnRemoveTimerByHandler = new Button() { Label = "Remove timer by handler" };
btnRemoveTimerByHandler.Clicked += delegate
{
if (timers.Count == 0)
return;
removeByHandler = true;
ApplicationOutput.WriteLine("Remove timer by handler");
};
var btnGc = new Button() { Label = "GC" };
btnGc.Clicked += delegate
{
ApplicationOutput.WriteLine("GC");
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
};
box.PackStart(btnAddTimer, false, false, 0);
box.PackStart(btnRemoveTimer, false, false, 0);
box.PackStart(btnRemoveTimerByHandler, false, false, 0);
box.PackStart(btnGc, false, false, 0);
}
}
}

View File

@@ -0,0 +1,14 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using System;
namespace Samples
{
class SectionAttribute : Attribute
{
public Type ContentType { get; set; }
public Category Category { get; set; }
}
}

View File

@@ -0,0 +1,71 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(Button), Category = Category.Widgets)]
class ButtonSection : ListSection
{
public ButtonSection()
{
AddItem(CreateSimpleButton());
AddItem(CreateStockButton());
AddItem(CreateImageButton());
AddItem(CreateImageTextButton());
AddItem(CreateActionButton());
}
public (string, Widget) CreateSimpleButton()
{
var btn = new Button("Simple Button");
btn.Clicked += (sender, e) => ApplicationOutput.WriteLine(sender, "Clicked");
return ("Simple button:", btn);
}
public (string, Widget) CreateStockButton()
{
var btn = new Button(Stock.About);
btn.Clicked += (sender, e) => ApplicationOutput.WriteLine(sender, "Clicked");
return ("Stock button:", btn);
}
public (string, Widget) CreateImageButton()
{
var btn = new Button();
btn.AlwaysShowImage = true;
btn.Image = Image.NewFromIconName("document-new-symbolic", IconSize.Button);
btn.Clicked += (sender, e) => ApplicationOutput.WriteLine(sender, "Clicked");
return ("Image button:", btn);
}
public (string, Widget) CreateImageTextButton()
{
var btn = new Button();
btn.Label = "Some text";
btn.ImagePosition = PositionType.Top;
btn.AlwaysShowImage = true;
btn.Image = Image.NewFromIconName("document-new-symbolic", IconSize.Button);
btn.Clicked += (sender, e) => ApplicationOutput.WriteLine(sender, "Clicked");
return ("Image and text button:", btn);
}
public (string, Widget) CreateActionButton()
{
var sa = new GLib.SimpleAction("SampleAction", null);
sa.Activated += (sender, e) => ApplicationOutput.WriteLine(sender, "SampleAction Activated");
Program.App.AddAction(sa);
var btn = new Button();
btn.Label = "SampleAction Button";
btn.ActionName = "app.SampleAction";
return ("Action button:", btn);
}
}
}

View File

@@ -0,0 +1,53 @@
using Gtk;
using System;
namespace Samples
{
[Section (ContentType = typeof(CustomCellRenderer), Category = Category.Widgets)]
class CellRendererSection : ListSection
{
public CellRendererSection ()
{
AddItem (CreateCellRenderer ());
}
ListStore liststore;
public (string, Widget) CreateCellRenderer ()
{
liststore = new ListStore (typeof (float), typeof (string));
liststore.AppendValues (0.5f, "50%");
TreeView view = new TreeView (liststore);
view.AppendColumn ("Progress", new CellRendererText (), "text", 1);
view.AppendColumn ("Progress", new CustomCellRenderer (), "percent", 0);
GLib.Timeout.Add (50, new GLib.TimeoutHandler (update_percent));
return (nameof(CustomCellRenderer), view);
}
bool increasing = true;
bool update_percent ()
{
TreeIter iter;
liststore.GetIterFirst (out iter);
float perc = (float) liststore.GetValue (iter, 0);
if ((perc > 0.99) || (perc < 0.01 && perc > 0)) {
increasing = !increasing;
}
if (increasing)
perc += 0.01f;
else
perc -= 0.01f;
liststore.SetValue (iter, 0, perc);
liststore.SetValue (iter, 1, Convert.ToInt32 (perc * 100) + "%");
return true;
}
}
}

View File

@@ -0,0 +1,38 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(ColorButton), Category = Category.Widgets)]
class ColorButtonSection : ListSection
{
public ColorButtonSection()
{
AddItem(CreateColorButton());
}
public (string, Widget) CreateColorButton()
{
var btn = new ColorButton();
// Set RGBA color
btn.Rgba = new Gdk.RGBA()
{
Red = 0,
Green = 0,
Blue = 255,
Alpha = 0.2 // 20% translucent
};
// Or Parse hex
btn.Rgba.Parse("#729FCF");
// UseAlpha default is false
btn.UseAlpha = true;
return ("Color button:", btn);
}
}
}

View File

@@ -0,0 +1,97 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(ComboBox), Category = Category.Widgets)]
class ComboBoxSection : ListSection
{
public ComboBoxSection()
{
AddItem(CreateSimpleComboBox());
AddItem(CreateMultiColumnComboBox());
AddItem(CreateEditableComboBox());
}
public (string, Widget) CreateSimpleComboBox()
{
// initialize with a simple string list
var combo = new ComboBox(
new string[]
{
"Combo Entry 1",
"Combo Entry 2",
"Combo Entry 3",
"Combo Entry 4"
}
);
// event to notify for index changes in our combo
combo.Changed += (sender, e) =>
ApplicationOutput.WriteLine(sender, $"Index changed to:{((ComboBox)sender).Active}");
// set the active selection to index 2 (Combo Entry 3)
combo.Active = 2;
return ("Simple combo:", combo);
}
public (string, Widget) CreateMultiColumnComboBox()
{
// create a store for our combo
var store = new ListStore(typeof(string), typeof(string), typeof(bool));
// lets append some stock icons, passing the icon names, and a simple text column
store.AppendValues("dialog-warning", "Warning", true);
store.AppendValues("process-stop", "Stop", false);
store.AppendValues("document-new", "New", true);
store.AppendValues("edit-clear", "Clear", true);
// create cells
var imageCell = new CellRendererPixbuf();
var textCell = new CellRendererText();
// create the combo and pass the values in
var combo = new ComboBox(store);
combo.PackStart(imageCell, true);
combo.PackStart(textCell, true);
// add combo attributes to show in columns
combo.AddAttribute(imageCell, "icon-name", 0);
combo.AddAttribute(textCell, "text", 1);
// lets use the store bool values to control sensitive rows
// Process-stop (store index one) should be disabled in this sample
// For a ComboBox item to be disabled, all cell renderers for the item need to have
// their sensitivity disabled
combo.AddAttribute(imageCell, "sensitive", 2);
combo.AddAttribute(textCell, "sensitive", 2);
// listen to index changed on combo
combo.Changed += (sender, e) =>
ApplicationOutput.WriteLine(sender, $"Index changed to:{((ComboBox)sender).Active}");
// lets preselect the first option
combo.Active = 0;
return ("Combo with Icons and Text:", combo);
}
public (string, Widget) CreateEditableComboBox()
{
var combo = ComboBoxText.NewWithEntry();
combo.AppendText("Example 1");
combo.AppendText("Example 2");
combo.AppendText("Example 3");
combo.AppendText("Example 4");
// combos with entry have a real entry inside it
// we can use it by
combo.Entry.PlaceholderText = "Write something";
return ("Combo with entry:", combo);
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(CompositeWidget), Category = Category.Widgets)]
class CompositeWidgetSection : ListSection
{
public CompositeWidgetSection()
{
AddItem("CompositeWidget:", new CompositeWidget());
AddItem("Other instance:", new CompositeWidget());
}
}
[Template("CompositeWidget.glade", true)]
[GLib.TypeName(nameof(CompositeWidget))]
class CompositeWidget : Bin
{
#pragma warning disable CS0649, CS0169
[Child] Button btn1;
[Child] Button btn2;
[Child("label")] Entry entry;
#pragma warning restore CS0649, CS0169
public CompositeWidget()
{
// Base constructor sets [Child] fields
// if [Template(throwOnUnknownChild = true) and GTK can't bind any [Child] field then base constructor throws
// GTK writes invalid field/widget name in console (project <OutputType> must be Exe to see console on Windows OS)
System.Diagnostics.Debug.Assert(btn1 != null);
System.Diagnostics.Debug.Assert(btn2 != null);
System.Diagnostics.Debug.Assert(entry != null);
}
private void on_btn1_clicked(object sender, EventArgs e)
{
entry.Text = DateTime.Now.ToString();
ApplicationOutput.WriteLine(this, "Instance handler clicked");
}
private static void on_btn2_clicked(object sender, EventArgs e)
{
ApplicationOutput.WriteLine("Static handler clicked");
}
}
}

View File

@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.18"/>
<template class="CompositeWidget" parent="GtkBin">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkButton" id="btn1">
<property name="label" translatable="yes">Instance handler</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-start">3</property>
<property name="margin-end">3</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
<signal name="clicked" handler="on_btn1_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="btn2">
<property name="label" translatable="yes">Static handler</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="margin-start">3</property>
<property name="margin-end">3</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
<signal name="clicked" handler="on_btn2_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="label">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="margin-start">3</property>
<property name="margin-end">3</property>
<property name="margin-top">3</property>
<property name="margin-bottom">3</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</template>
</interface>

View File

@@ -0,0 +1,77 @@
// CustomCellRenderer.cs : C# implementation of an example custom cellrenderer
// from http://scentric.net/tutorial/sec-custom-cell-renderers.html
//
// Author: Todd Berman <tberman@sevenl.net>
//
// (c) 2004 Todd Berman
// adopted from: https://github.com/mono/gtk-sharp/commits/2.99.3/sample/CustomCellRenderer.cs
using System;
using Gtk;
using Gdk;
using GLib;
namespace Samples
{
public class CustomCellRenderer : CellRenderer
{
private float percent;
[GLib.Property ("percent")]
public float Percentage {
get { return percent; }
set { percent = value; }
}
protected override void OnGetSize (Widget widget, ref Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height)
{
base.OnGetSize (widget, ref cell_area, out x_offset, out y_offset, out width, out height);
int calc_width = (int) this.Xpad * 2 + 100;
int calc_height = (int) this.Ypad * 2 + 10;
width = calc_width;
height = calc_height;
x_offset = 0;
y_offset = 0;
if (!cell_area.Equals (Rectangle.Zero)) {
x_offset = (int) (this.Xalign * (cell_area.Width - calc_width));
x_offset = Math.Max (x_offset, 0);
y_offset = (int) (this.Yalign * (cell_area.Height - calc_height));
y_offset = Math.Max (y_offset, 0);
}
}
protected override void OnRender (Cairo.Context cr, Widget widget, Rectangle background_area, Rectangle cell_area, CellRendererState flags)
{
int x = (int) (cell_area.X + this.Xpad);
int y = (int) (cell_area.Y + this.Ypad);
int width = (int) (cell_area.Width - this.Xpad * 2);
int height = (int) (cell_area.Height - this.Ypad * 2);
widget.StyleContext.Save ();
widget.StyleContext.AddClass ("trough");
widget.StyleContext.RenderBackground (cr, x, y, width, height);
widget.StyleContext.RenderFrame (cr, x, y, width, height);
Border padding = widget.StyleContext.GetPadding (StateFlags.Normal);
x += padding.Left;
y += padding.Top;
width -= padding.Left + padding.Right;
height -= padding.Top + padding.Bottom;
widget.StyleContext.Restore ();
widget.StyleContext.Save ();
widget.StyleContext.AddClass ("progressbar");
widget.StyleContext.RenderActivity (cr, x, y, (int) (width * Percentage), height);
widget.StyleContext.Restore ();
}
}
}

View File

@@ -0,0 +1,110 @@
// adopted from: https://github.com/mono/xwt/blob/master/Xwt.XamMac/Xwt.Mac/ImageHandler.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Gtk;
using Gdk;
using System.Runtime.InteropServices;
using Cairo;
using Rectangle = Gdk.Rectangle;
namespace Samples
{
// This is a completely pointless widget, but its for testing subclassing Widget.OnDrawn
public class GtkDrawingArea : Gtk.DrawingArea { }
public class ImageBox : GtkDrawingArea
{
Pixbuf image;
float yalign = 0.5f, xalign = 0.5f;
public ImageBox(Pixbuf img) : this()
{
Image = img;
}
public ImageBox()
{
this.HasWindow = false;
this.AppPaintable = true;
}
public Pixbuf Image {
get { return image; }
set {
image = value;
SetSizeRequest((int) image.Width, (int) image.Height);
//QueueDraw();
}
}
private Size SizeRequestet { get; set; }
public float Yalign {
get { return yalign; }
set {
yalign = value;
QueueDraw();
}
}
public float Xalign {
get { return xalign; }
set {
xalign = value;
QueueDraw();
}
}
void DrawPixbuf(Cairo.Context ctx, Gdk.Pixbuf img, double x, double y, Size idesc)
{
ctx.Save();
ctx.Translate(x, y);
ctx.Scale(idesc.Width / (double) img.Width, idesc.Height / (double) img.Height);
Gdk.CairoHelper.SetSourcePixbuf(ctx, img, 0, 0);
#pragma warning disable 618
using (var p = ctx.Source) {
if (p is SurfacePattern pattern) {
if (idesc.Width > img.Width || idesc.Height > img.Height) {
// Fixes blur issue when rendering on an image surface
pattern.Filter = Cairo.Filter.Fast;
} else
pattern.Filter = Cairo.Filter.Good;
}
}
#pragma warning restore 618
ctx.Paint();
ctx.Restore();
}
protected override bool OnDrawn(Cairo.Context cr)
{
if (image == default)
return true;
var a = Allocation;
var size = Allocation.Size;
Pixbuf pixbuff = image;
// HACK: Gtk sends sometimes an expose/draw event while the widget reallocates.
// In that case we would draw in the wrong area, which may lead to artifacts
// if no other widget updates it. Alternative: we could clip the
// allocation bounds, but this may have other issues.
if (a.Width == 1 && a.Height == 1 && a.X == -1 && a.Y == -1) // the allocation coordinates on reallocation
return base.OnDrawn(cr);
var x = (int) ((a.Width - (float) pixbuff.Width) * xalign);
var y = (int) ((a.Height - (float) pixbuff.Height) * yalign);
if (x < 0) x = 0;
if (y < 0) y = 0;
DrawPixbuf(cr, pixbuff, x, y, size);
return base.OnDrawn(cr);
}
}
}

View File

@@ -0,0 +1,196 @@
// adopted from: https://github.com/mono/gtk-sharp/commits/2.99.3/sample/PolarFixed.cs
// This is a completely pointless widget, but it shows how to subclass container...
using System;
using System.Collections.Generic;
using Gtk;
using Gdk;
namespace Samples
{
class PolarFixed : Container
{
IList<PolarFixedChild> children;
public PolarFixed()
{
children = new List<PolarFixedChild>();
HasWindow = false;
}
// The child properties object
public class PolarFixedChild : Container.ContainerChild
{
double theta;
uint r;
public PolarFixedChild(PolarFixed parent, Widget child, double theta, uint r) : base(parent, child)
{
this.theta = theta;
this.r = r;
}
// We call parent.QueueResize() from the property setters here so that you
// can move the widget around just by changing its child properties (just
// like with a native container class).
public double Theta {
get { return theta; }
set {
theta = value;
parent.QueueResize();
}
}
public uint R {
get { return r; }
set {
r = value;
parent.QueueResize();
}
}
}
// Override the child properties accessor to return the right object from
// "children".
public override ContainerChild this[Widget w] {
get {
foreach (PolarFixedChild pfc in children) {
if (pfc.Child == w)
return pfc;
}
return null;
}
}
// Indicate the kind of children the container will accept. Most containers
// will accept any kind of child, so they should return Gtk.Widget.GType.
// The default is "GLib.GType.None", which technically means that no (new)
// children can be added to the container, though Container.Add does not
// enforce this.
protected override GLib.GType OnChildType()
{
return Gtk.Widget.GType;
}
// Implement gtk_container_forall(), which is also used by
// Gtk.Container.Children and Gtk.Container.AllChildren.
protected override void ForAll(bool include_internals, Callback callback)
{
base.ForAll(include_internals, callback);
foreach (PolarFixedChild pfc in children)
callback(pfc.Child);
}
// Invoked by Container.Add (w). It's good practice to have this do *something*,
// even if it's not something terribly useful.
protected override void OnAdded(Widget w)
{
Put(w, 0.0, 0);
}
// our own adder method
public void Put(Widget w, double theta, uint r)
{
children.Add(new PolarFixedChild(this, w, theta, r));
w.Parent = this;
QueueResize();
}
public void Move(Widget w, double theta, uint r)
{
PolarFixedChild pfc = (PolarFixedChild) this[w];
if (pfc != null) {
pfc.Theta = theta;
pfc.R = r;
}
}
// invoked by Container.Remove (w)
protected override void OnRemoved(Widget w)
{
PolarFixedChild pfc = (PolarFixedChild) this[w];
if (pfc != null) {
pfc.Child.Unparent();
children.Remove(pfc);
QueueResize();
}
}
// Handle size request
protected override void OnGetPreferredHeight(out int minimal_height, out int natural_height)
{
Requisition req = new Requisition();
OnSizeRequested(ref req);
minimal_height = natural_height = req.Height;
}
protected override void OnGetPreferredWidth(out int minimal_width, out int natural_width)
{
Requisition req = new Requisition();
OnSizeRequested(ref req);
minimal_width = natural_width = req.Width;
}
void OnSizeRequested(ref Requisition req)
{
int child_width, child_minwidth, child_height, child_minheight;
int x, y;
req.Width = req.Height = 0;
foreach (PolarFixedChild pfc in children) {
// Recursively request the size of each child
pfc.Child.GetPreferredWidth(out child_minwidth, out child_width);
pfc.Child.GetPreferredHeight(out child_minheight, out child_height);
// Figure out where we're going to put it
x = (int) (Math.Cos(pfc.Theta) * pfc.R) + child_width / 2;
y = (int) (Math.Sin(pfc.Theta) * pfc.R) + child_height / 2;
// Update our own size request to fit it
if (req.Width < 2 * x)
req.Width = 2 * x;
if (req.Height < 2 * y)
req.Height = 2 * y;
}
// Take Container.BorderWidth into account
req.Width += (int) (2 * BorderWidth);
req.Height += (int) (2 * BorderWidth);
}
// Size allocation. Note that the allocation received may be smaller than what we
// requested. Some containers will take that into account by giving some or all
// of their children a smaller allocation than they requested. Other containers
// (like this one) just let their children get placed partly out-of-bounds if they
// aren't allocated enough room.
protected override void OnSizeAllocated(Rectangle allocation)
{
Requisition childReq, childMinReq;
int cx, cy, x, y;
// This sets the "Allocation" property. For widgets that
// have a GdkWindow, it also calls GdkWindow.MoveResize()
base.OnSizeAllocated(allocation);
// Figure out where the center of the grid will be
cx = allocation.X + (allocation.Width / 2);
cy = allocation.Y + (allocation.Height / 2);
foreach (PolarFixedChild pfc in children) {
pfc.Child.GetPreferredSize(out childMinReq, out childReq);
x = (int) (Math.Cos(pfc.Theta) * pfc.R) - childReq.Width / 2;
y = (int) (Math.Sin(pfc.Theta) * pfc.R) + childReq.Height / 2;
allocation.X = cx + x;
allocation.Width = childReq.Width;
allocation.Y = cy - y;
allocation.Height = childReq.Height;
pfc.Child.SizeAllocate(allocation);
}
}
}
}

View File

@@ -0,0 +1,138 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
// Ported from https://developer.gnome.org/gtkmm-tutorial/3.24/gtkmm-tutorial.html
using Cairo;
using Gtk;
using System;
namespace Samples
{
[Section(ContentType = typeof(DrawingArea), Category = Category.Widgets)]
class DrawingAreaSection : ListSection
{
public DrawingAreaSection()
{
AddItem(DrawCircles());
AddItem(DrawText());
}
public (string, Widget) DrawCircles()
{
DrawingArea drawingArea = new DrawingArea();
drawingArea.SetSizeRequest(50,50);
drawingArea.Drawn += DrawingAreaCirclesOnDrawn;
return ("Draw Circles :", drawingArea);
}
public (string, Widget) DrawText()
{
DrawingArea drawingArea = new DrawingArea();
drawingArea.SetSizeRequest(200,100);
drawingArea.Drawn += DrawingAreaTextOnDrawn;
return ("Draw Pango Text :", drawingArea);
}
private void DrawingAreaCirclesOnDrawn(object o, DrawnArgs args)
{
if (o is DrawingArea da)
{
Context cr = args.Cr;
int width = da.Allocation.Width;
int height = da.Allocation.Height;
cr.LineWidth = 5;
cr.SetSourceRGB(0.8, 0.8, 0.8);
cr.Rectangle(0, 0, width, height);
cr.Fill();
cr.SetSourceRGB(0.9, 0, 0);
cr.Translate(width/2d, height/2d);
cr.Arc(0, 0, (width < height ? width : height) / 2 - 10, 0, 2*Math.PI);
cr.StrokePreserve();
cr.SetSourceRGB(0, 0.9, 0);
cr.Fill();
cr.GetTarget().Dispose();
cr.Dispose();
}
}
private void DrawingAreaTextOnDrawn(object o, DrawnArgs args)
{
if (o is DrawingArea da)
{
Context cr = args.Cr;
int width = da.Allocation.Width;
int height = da.Allocation.Height;
int rectangle_width = width;
int rectangle_height = height / 2;
// Draw a black rectangle
cr.SetSourceRGB(0, 0, 0);
cr.Rectangle(0, 0, rectangle_width, rectangle_height);
cr.Fill();
// and some white text
cr.SetSourceRGB(1.0, 1.0, 1.0);
draw_text(cr, rectangle_width, rectangle_height, "Hi there!");
// flip the image vertically
// see http://www.cairographics.org/documentation/cairomm/reference/classCairo_1_1Matrix.html
// the -1 corresponds to the yy part (the flipping part)
// the height part is a translation (we could have just called cr->translate(0, height) instead)
// it's height and not height / 2, since we want this to be on the second part of our drawing
// (otherwise, it would draw over the previous part)
Cairo.Matrix matrix = new Matrix(1.0, 0.0, 0.0, -1.0, 0.0, height);
// apply the matrix
cr.Transform(matrix);
// white rectangle
cr.SetSourceRGB(1.0, 1.0, 1.0);
cr.Rectangle(0, 0, rectangle_width, rectangle_height);
cr.Fill();
// black text
cr.SetSourceRGB(0, 0, 0);
draw_text(cr, rectangle_width, rectangle_height, "Hi there!");
cr.GetTarget().Dispose();
cr.Dispose();
}
}
private void draw_text(Context cr, int rectangle_width, int rectangle_height, string text)
{
// http://developer.gnome.org/pangomm/unstable/classPango_1_1FontDescription.html
Pango.FontDescription font = new Pango.FontDescription();
font.Family = "Monospace";
font.Weight = Pango.Weight.Bold;
// http://developer.gnome.org/pangomm/unstable/classPango_1_1Layout.html
Pango.Layout layout = CreatePangoLayout(text);
layout.FontDescription = font;
int text_width;
int text_height;
//get the text dimensions (it updates the variables -- by reference)
layout.GetPixelSize(out text_width, out text_height);
// Position the text in the middle
cr.MoveTo((rectangle_width - text_width) / 2d, (rectangle_height - text_height) / 2d);
Pango.CairoHelper.ShowLayout(cr, layout);
}
}
}

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

View File

@@ -0,0 +1,163 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(Entry), Category = Category.Widgets)]
class EntrySection : ListSection
{
public EntrySection()
{
AddItem(CreateSimpleEntry());
AddItem(CreateSimpleRightAlignedTextEntry());
AddItem(CreateMaxLimitEntry());
AddItem(CreatePlaceholderEntry());
AddItem(CreateInvisibleCharEntry());
AddItem(CreateCustomActionsEntry());
AddItem(CreateProgressEntry());
AddItem(CreateCompletionEntry());
AddItem(CreateInsensitiveEntry());
}
public (string, Widget) CreateSimpleEntry()
{
var entry = new Entry("Initial Text");
entry.TooltipText = "This is the tooltip!";
entry.Changed += (sender, e) => ApplicationOutput.WriteLine(sender, "Changed");
return ("Simple entry:", entry);
}
public (string, Widget) CreateSimpleRightAlignedTextEntry()
{
var entry = new Entry("Text is Right Aligned");
entry.Xalign = 1f;
entry.Changed += (sender, e) => ApplicationOutput.WriteLine(sender, "Changed");
return ("Right aligned text entry:", entry);
}
public (string, Widget) CreateMaxLimitEntry()
{
var entry = new Entry("123");
entry.MaxLength = 3;
entry.Changed += (sender, e) => ApplicationOutput.WriteLine(sender, "Changed");
return ("Text length limited entry:", entry);
}
public (string, Widget) CreatePlaceholderEntry()
{
var entry = new Entry();
entry.PlaceholderText = "Please fill with information";
entry.Changed += (sender, e) => ApplicationOutput.WriteLine(sender, "Changed");
return ("Placeholder text entry:", entry);
}
public (string, Widget) CreateInvisibleCharEntry()
{
var entry = new Entry("Invisible text entry");
entry.Visibility = false;
entry.InvisibleChar = '\u2022';
entry.InvisibleCharSet = true;
entry.Changed += (sender, e) => ApplicationOutput.WriteLine(sender, "Changed");
return ("Invisible text entry:", entry);
}
public (string, Widget) CreateCustomActionsEntry()
{
var entry = new Entry();
entry.PlaceholderText = "Search";
entry.SetIconFromIconName(EntryIconPosition.Primary, "edit-find-symbolic");
entry.SetIconFromIconName(EntryIconPosition.Secondary, "edit-clear-symbolic");
entry.IconRelease += (o, args) =>
{
switch (args.P0)
{
case EntryIconPosition.Primary:
ApplicationOutput.WriteLine(o, "Clicked Search Icon");
break;
default:
entry.Text = string.Empty;
ApplicationOutput.WriteLine(o, "Clicked Clear Icon");
break;
}
};
return ("Custom actions entry:", entry);
}
public (string, Widget) CreateProgressEntry()
{
var entry = new Entry();
entry.PlaceholderText = "Progress Entry";
entry.ProgressFraction = 0f;
entry.MaxLength = 20;
entry.Changed += (sender, e) => entry.ProgressFraction = (float)entry.Text.Length / entry.MaxLength;
return ("Progress entry:", entry);
}
public (string, Widget) CreateCompletionEntry()
{
// create completion object and assign it to entry
var completion = new EntryCompletion();
var entry = new Entry();
entry.Completion = completion;
// create values store
var store = new ListStore(typeof(string));
store.AppendValues("An example to search for");
store.AppendValues("Better example");
store.AppendValues("Better and bigger example");
store.AppendValues("Some other example");
// assign treemodel as the completion
completion.Model = store;
// lets override the default match function so we can use the contains mode
// instead of the default startswith
completion.MatchFunc = (EntryCompletion comp, string key, TreeIter iter) =>
{
if (string.IsNullOrEmpty(key))
return false;
var o = comp.Model.GetValue(iter, 0);
var stringToSearch = o as string;
if (!string.IsNullOrEmpty(stringToSearch))
return stringToSearch.IndexOf(key, System.StringComparison.InvariantCultureIgnoreCase) >= 0;
return false;
};
completion.TextColumn = 0;
return ("Completion Entry:",entry);
}
public (string, Widget) CreateInsensitiveEntry()
{
var entry = new Entry();
entry.Text = "Cannot change this";
entry.Sensitive = false;
return ("Insensitive entry:", entry);
}
}
}

View File

@@ -0,0 +1,30 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Atk;
using Gdk;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(ImageBox), Category = Category.Widgets)]
class ImageSection : ListSection
{
public ImageSection()
{
AddItem(CreateContainer());
}
public (string, Widget) CreateContainer()
{
var image = new Pixbuf(typeof(ImageSection).Assembly, "Testpic");
var container = new ImageBox(image);
return ($"{nameof(ImageBox)}:", container);
}
}
}

View File

@@ -0,0 +1,47 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(Label), Category = Category.Widgets)]
class LabelSection : ListSection
{
public LabelSection()
{
AddItem(CreateSimpleLabel());
AddItem(CreateMarkupLabel());
}
public (string, Widget) CreateSimpleLabel()
{
var label = new Label();
// can be defined at constructor
label.LabelProp = "This is a label";
// right align text, center is default
label.Xalign = 1f;
return ("Label :", label);
}
public (string, Widget) CreateMarkupLabel()
{
var label = new Label();
// activate markup, default is false
label.UseMarkup = true;
// define label with pango markup
label.LabelProp = "This is a <span foreground=\"red\" size=\"large\">label</span> with <b>custom</b> markup";
// right align text, center is default
label.Xalign = 1f;
return ("Label Markup:", label);
}
}
}

View File

@@ -0,0 +1,31 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(LevelBar), Category = Category.Widgets)]
class LevelBarSection : ListSection
{
public LevelBarSection()
{
AddItem(CreateSimpleLevelBar());
}
public (string, Widget) CreateSimpleLevelBar()
{
// constructor takes MinValue, MaxValue
var lb = new LevelBar(0, 100);
// lets add a visible request size in our example
lb.WidthRequest = 100;
// set the value to 75%
lb.Value = 75d;
return ("Level Bar:", lb);
}
}
}

View File

@@ -0,0 +1,25 @@

// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(LinkButton), Category = Category.Widgets)]
class LinkButtonSection : ListSection
{
public LinkButtonSection()
{
AddItem(CreateLinkButton());
}
public (string, Widget) CreateLinkButton()
{
var btn = new LinkButton("A simple link button");
btn.Clicked += (sender, e) => ApplicationOutput.WriteLine(sender, "Link button Clicked");
return ("Link button:", btn);
}
}
}

View File

@@ -0,0 +1,194 @@
using System.Collections.Generic;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(ListStore), Category = Category.Widgets)]
class ListStoreSection : Box
{
private readonly TreeView _tree;
private ListStore _model;
private readonly List<Bug> _data = new List<Bug>
{
new Bug ( false, 60482, "Normal", "scrollable notebooks and hidden tabs" ),
new Bug ( false, 60620, "Critical", "gdk_window_clear_area (gdkwindow-win32.c) is not thread-safe" ),
new Bug ( false, 50214, "Major", "Xft support does not clean up correctly" ),
new Bug ( true, 52877, "Major", "GtkFileSelection needs a refresh method. " ),
new Bug ( false, 56070, "Normal", "Can't click button after setting in sensitive" ),
new Bug ( true, 56355, "Normal", "GtkLabel - Not all changes propagate correctly" ),
new Bug ( false, 50055, "Normal", "Rework width/height computations for TreeView" ),
new Bug ( false, 58278, "Normal", "gtk_dialog_set_response_sensitive () doesn't work" ),
new Bug ( false, 55767, "Normal", "Getters for all setters" ),
new Bug ( false, 56925, "Normal", "Gtkcalender size" ),
new Bug ( false, 56221, "Normal", "Selectable label needs right-click copy menu" ),
new Bug ( true, 50939, "Normal", "Add shift clicking to GtkTextView" ),
new Bug ( false, 6112, "Enhancement", "netscape-like collapsable toolbars" ),
new Bug ( false, 1, "Normal", "First bug :=)" ),
};
public ListStoreSection() : base(Orientation.Vertical, 3)
{
CreateModel();
_tree = new TreeView(_model);
AddColumn();
var treeScroll = new ScrolledWindow
{
Expand = true
};
treeScroll.Add(_tree);
PackStart(treeScroll, true, true, 0);
GLib.Timeout.Add(100, SpinerTimeout);
}
private enum Column
{
Fixed,
Number,
Severity,
Description,
Pulse,
Icon,
Active,
Sensitive,
Num
};
private readonly struct Bug
{
public bool Fixed { get; }
public int Number { get; }
public string Severity { get; }
public string Description { get; }
public Bug(bool isFixed, int number, string severity, string description)
{
Fixed = isFixed;
Number = number;
Severity = severity;
Description = description;
}
}
private void CreateModel()
{
/* create list store */
_model = new ListStore(typeof(bool), typeof(int), typeof(string), typeof(string), typeof(int), typeof(string), typeof(bool), typeof(bool));
/* add data to the list store */
for (int i = 0; i < _data.Count; i++)
{
string iconName;
bool sensitive;
if (i == 1 || i == 3)
iconName = "battery-caution-charging-symbolic";
else
iconName = null;
if (i == 3)
sensitive = false;
else
sensitive = true;
TreeIter iter = _model.Append();
_model.SetValue(iter, (int)Column.Fixed, _data[i].Fixed);
_model.SetValue(iter, (int)Column.Number, _data[i].Number);
_model.SetValue(iter, (int)Column.Severity, _data[i].Severity);
_model.SetValue(iter, (int)Column.Description, _data[i].Description);
_model.SetValue(iter, (int)Column.Pulse, 5);
_model.SetValue(iter, (int)Column.Icon, iconName);
_model.SetValue(iter, (int)Column.Active, false);
_model.SetValue(iter, (int)Column.Sensitive, sensitive);
}
}
private void AddColumn()
{
CellRenderer renderer;
TreeViewColumn column;
/* column for fixed toggles */
var rendererToggle = new CellRendererToggle();
rendererToggle.Toggled += RendererToggle_Toggled;
column = new TreeViewColumn("Fixed?", rendererToggle, "active", Column.Fixed, null)
{
/* set this column to a fixed sizing (of 50 pixels) */
FixedWidth = 50
};
_tree.AppendColumn(column);
/* column for bug numbers */
renderer = new CellRendererText();
column = new TreeViewColumn("Bug number", renderer, "text", Column.Number, null);
column.SortColumnId = (int)Column.Number;
_tree.AppendColumn(column);
/* column for severities */
renderer = new CellRendererText();
column = new TreeViewColumn("Severity", renderer, "text", Column.Severity, null)
{
SortColumnId = (int)Column.Severity
};
_tree.AppendColumn(column);
/* column for description */
renderer = new CellRendererText();
column = new TreeViewColumn("Description", renderer, "text", Column.Description, null)
{
SortColumnId = (int)Column.Description
};
_tree.AppendColumn(column);
/* column for spinner */
renderer = new CellRendererSpinner();
column = new TreeViewColumn("Spinning", renderer, "pulse", Column.Pulse, "active", Column.Active, null)
{
SortColumnId = (int)Column.Pulse
};
_tree.AppendColumn(column);
/* column for symbolic icon */
renderer = new CellRendererPixbuf();
column = new TreeViewColumn("Symbolic icon", renderer, "icon-name", Column.Icon, "sensitive", Column.Sensitive, null);
column.SortColumnId = (int)Column.Icon;
_tree.AppendColumn(column);
}
private void RendererToggle_Toggled(object o, ToggledArgs args)
{
TreePath path = new TreePath(args.Path);
/* get toggled iter */
TreeIter iter;
_model.GetIter(out iter, path);
bool isFixed = (bool)_model.GetValue(iter, (int)Column.Fixed);
/* do something with the value */
isFixed ^= true;
/* set new value */
_model.SetValue(iter, (int)Column.Fixed, isFixed);
}
private bool SpinerTimeout()
{
if (_model == null)
{
return false;
}
_model.GetIterFirst(out TreeIter iter);
int pulse = (int)_model.GetValue(iter, (int)Column.Pulse);
if (pulse == int.MaxValue)
pulse = 0;
else
pulse++;
_model.SetValue(iter, (int)Column.Pulse, pulse);
_model.SetValue(iter, (int)Column.Active, true);
return true;
}
}
}

View File

@@ -0,0 +1,95 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
using System;
using System.Timers;
namespace Samples
{
[Section(ContentType = typeof(ProgressBar), Category = Category.Widgets)]
class ProgressBarSection : ListSection
{
public ProgressBarSection()
{
AddItem(CreateSimpleProgressBar());
AddItem(CreateFractionProgressBar());
AddItem(CreatePulseProgressBar());
}
public (string, Widget) CreateSimpleProgressBar()
{
var pb = new ProgressBar();
// lets add a visible request size in our example
pb.WidthRequest = 100;
// add a text
pb.Text = "Some progress...";
// to show text it must be set to true
pb.ShowText = true;
// progressbar is used in percentage mode values between 0.0 and 1.0
pb.Fraction = 0.60d;
return ("Progress Bar:", pb);
}
public (string, Widget) CreateFractionProgressBar()
{
// this is used when application can report progress
var pb = new ProgressBar();
pb.WidthRequest = 200;
pb.Text = "0%";
pb.ShowText = true;
pb.Fraction = 0d;
// lets add a timer to demo it
var timer = new Timer();
timer.Interval = 1000;
timer.Elapsed += (sender, e) =>
{
pb.Fraction += 0.1d;
if (pb.Fraction >= 1d)
pb.Fraction = 0d;
pb.Text = $"{Math.Truncate(pb.Fraction * 100)}%";
};
timer.Start();
return ("Progress Bar with fraction:", pb);
}
public (string, Widget) CreatePulseProgressBar()
{
// this is used when application can't report progress
var pb = new ProgressBar();
pb.WidthRequest = 200;
pb.Text = "Task time is unknown";
pb.ShowText = true;
// define how much is the pulse step
pb.PulseStep = 0.1d;
// lets add a timer to demo it
var timer = new Timer();
timer.Interval = 200;
timer.Elapsed += (sender, e) => pb.Pulse();
timer.Start();
return ("Progress Bar with pulse:", pb);
}
}
}

View File

@@ -0,0 +1,35 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(Range), Category = Category.Widgets)]
class RangeSection : ListSection
{
public RangeSection()
{
AddItem(CreateHorizontalRange());
AddItem(CreateVerticalRange());
}
public (string, Widget) CreateHorizontalRange()
{
var adj = new Adjustment(0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
var hScale = new HScale(adj);
hScale.SetSizeRequest(200, -1);
hScale.ValueChanged += (sender, e) => ApplicationOutput.WriteLine(sender, $"Value Change: {((HScale)sender).Value}");
return ("Horizontal", hScale);
}
public (string, Widget) CreateVerticalRange()
{
var adj = new Adjustment(0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
var vScale = new VScale(adj);
vScale.SetSizeRequest(-1, 200);
vScale.ValueChanged += (sender, e) => ApplicationOutput.WriteLine(sender, $"Value Change: {((VScale)sender).Value}");
return ("Vertical", vScale);
}
}
}

View File

@@ -0,0 +1,32 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(SpinButton), Category = Category.Widgets)]
class SpinButtonSection : ListSection
{
public SpinButtonSection()
{
AddItem(CreateSpinButton());
}
public (string, Widget) CreateSpinButton()
{
// Spinbutton constructor takes MinValue, MaxValue and StepValue
var btn = new SpinButton(0, 1000, 1);
// Button constructor also takes the adjustment object
// and it can be redefined any time like CurrentVal, MinVal, MaxVal, Step, PageStep, PageSize
btn.Adjustment.Configure(888, 0, 1000, 1, 100, 0);
// Default values are double, use ValueAsInt method to get Int
btn.ValueChanged += (sender, e) =>
ApplicationOutput.WriteLine(sender, $"Spin button changed: {btn.ValueAsInt}");
return ("Spin button:", btn);
}
}
}

View File

@@ -0,0 +1,28 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(Spinner), Category = Category.Widgets)]
class SpinnerSection : ListSection
{
public SpinnerSection()
{
AddItem(CreateSimpleSpinner());
}
public (string, Widget) CreateSimpleSpinner()
{
var sp = new Spinner();
sp.Start();
// can be stopped with
// Stop()
return ("Simple Spinner:", sp);
}
}
}

View File

@@ -0,0 +1,26 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(Switch), Category = Category.Widgets)]
class SwitchSection : ListSection
{
public SwitchSection()
{
AddItem(CreateSwitchButton());
}
public (string, Widget) CreateSwitchButton()
{
var btn = new Switch();
btn.ButtonReleaseEvent += (o, args) =>
ApplicationOutput.WriteLine(o, $"Switch is now: {!btn.Active}");
return ("Switch:", btn);
}
}
}

View File

@@ -0,0 +1,32 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(ToggleButton), Category = Category.Widgets)]
class ToggleButtonSection : ListSection
{
public ToggleButtonSection()
{
AddItem(CreateToggleButton());
}
public (string, Widget) CreateToggleButton()
{
var btn = new ToggleButton("Toggle Me");
btn.Toggled += (sender, e) =>
{
if (btn.Active)
btn.Label = "Untoggle Me";
else
btn.Label = "Toglle Me";
ApplicationOutput.WriteLine(sender, "Buton Toggled");
};
return ("Toggle button:", btn);
}
}
}

View File

@@ -0,0 +1,177 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using System;
using Gtk;
namespace Samples
{
[Section(ContentType = typeof(TreeView), Category = Category.Widgets)]
class TreeViewSection : Box
{
const int ColumnIndex = 0;
const int ColumnName = 1;
const int ColumnIcon = 2;
TreeView tree;
TreeStore store;
Entry entry;
Gdk.Pixbuf icon = new Gdk.Pixbuf(typeof(ImageSection).Assembly, "Testpic", 32, 32);
public TreeViewSection() : base(Orientation.Vertical, 3)
{
CreateTreeView();
var treeScroll = new ScrolledWindow();
treeScroll.Expand = true;
treeScroll.Add(tree);
var boxEdit = new Box(Orientation.Horizontal, 3);
var btn1 = new Button() { Label = "Add" };
btn1.Clicked += OnAddClicked;
var btn2 = new Button() { Label = "Edit" };
btn2.Clicked += OnEditClicked;
var btn3 = new Button() { Label = "Remove" };
btn3.Clicked += OnRemoveClicked;
entry = new Entry();
boxEdit.PackStart(entry, true, true, 0);
boxEdit.PackStart(btn1, false, true, 0);
boxEdit.PackStart(btn2, false, true, 0);
boxEdit.PackStart(btn3, false, true, 0);
PackStart(boxEdit, false, true, 0);
PackStart(treeScroll, true, true, 0);
}
void CreateTreeView()
{
store = new TreeStore(typeof(int), typeof(string), typeof(Gdk.Pixbuf));
store.RowInserted += OnStoreRowInserted;
store.RowDeleted += OnStoreRowDeleted;
store.RowChanged += OnStoreRowChanged;
store.RowsReordered += OnStoreRowsReordered;
store.RowHasChildToggled += OnStoreRowHasChildToggled;
tree = new TreeView();
var col = tree.AppendColumn("Index", new CellRendererText(), "text", ColumnIndex);
col.Resizable = true;
col.SortColumnId = 0;
col = tree.AppendColumn("Name", new CellRendererText(), "text", ColumnName);
col.Resizable = true;
col.Expand = true;
col.SortColumnId = 1;
col = tree.AppendColumn("Icon", new CellRendererPixbuf(), "pixbuf", ColumnIcon);
col.Resizable = true;
col.Expand = true;
col.Alignment = .5f;
FillTreeView();
tree.Model = store;
tree.Selection.Changed += OnTreeSelectionChanged;
}
void FillTreeView()
{
int idx = 0;
TreeIter it = store.InsertWithValues(-1, idx++, "Adam", null);
store.InsertWithValues(it, -1, idx++, "Adam child 1", null);
store.InsertWithValues(it, -1, idx++, "Adam child 2", icon);
store.InsertWithValues(it, -1, idx++, "Adam child 3", null);
store.InsertWithValues(-1, idx++, "Eve", null);
store.InsertWithValues(-1, idx++, "Zack", null);
store.InsertWithValues(-1, idx++, "John", icon);
it = store.InsertWithValues(-1, idx++, "Amy", null);
store.InsertWithValues(it, -1, idx++, "Amy child 1", null);
store.InsertWithValues(it, -1, idx++, "Amy child 2", null);
store.InsertWithValues(-1, idx++, "William", null);
store.InsertWithValues(-1, idx++, "Evelyn", icon);
store.InsertWithValues(-1, idx++, "Wyatt", null);
}
private void OnTreeSelectionChanged(object sender, EventArgs e)
{
if (!tree.Selection.GetSelected(out TreeIter it))
return;
TreePath path = store.GetPath(it);
var name = (string)store.GetValue(it, ColumnName);
entry.Text = name;
ApplicationOutput.WriteLine(sender, $"SelectionChanged, path {path}, name {name}");
}
private void OnStoreRowInserted(object sender, RowInsertedArgs args)
{
var name = (string)store.GetValue(args.Iter, ColumnName);
ApplicationOutput.WriteLine(sender, $"RowInserted, path {args.Path}, name {name}");
}
private void OnStoreRowDeleted(object sender, RowDeletedArgs args)
{
ApplicationOutput.WriteLine(sender, $"RowDeleted, path {args.Path}");
}
private void OnStoreRowChanged(object sender, RowChangedArgs args)
{
var name = (string)store.GetValue(args.Iter, ColumnName);
ApplicationOutput.WriteLine(sender, $"RowChanged, path {args.Path}, name {name}");
}
private void OnStoreRowsReordered(object sender, RowsReorderedArgs args)
{
ApplicationOutput.WriteLine(sender, $"RowsReordered, path {args.Path}");
}
private void OnStoreRowHasChildToggled(object sender, RowHasChildToggledArgs args)
{
var name = (string)store.GetValue(args.Iter, ColumnName);
ApplicationOutput.WriteLine(sender, $"RowHasChildToggled, path {args.Path}, name {name}");
}
private void OnAddClicked(object sender, EventArgs e)
{
if (!tree.Selection.GetSelected(out TreeIter it))
return;
string txt = entry.Text.Trim();
if (string.IsNullOrEmpty(txt))
return;
int idx = Environment.TickCount % 100;
store.InsertWithValues(it, -1, idx, txt, null);
}
private void OnEditClicked(object sender, EventArgs e)
{
if (!tree.Selection.GetSelected(out TreeIter it))
return;
string txt = entry.Text.Trim();
if (string.IsNullOrEmpty(txt))
return;
store.SetValue(it, ColumnName, txt);
}
private void OnRemoveClicked(object sender, EventArgs e)
{
if (!tree.Selection.GetSelected(out TreeIter it))
return;
store.Remove(ref it);
}
}
}

View File

@@ -0,0 +1,145 @@
// This is free and unencumbered software released into the public domain.
// Happy coding!!! - GtkSharp Team
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Atk;
using Gdk;
using Gtk;
using WebKit;
using IAsyncResult = GLib.IAsyncResult;
using Object = GLib.Object;
namespace Samples
{
[Section(ContentType = typeof(WebView), Category = Category.Widgets)]
class WebviewSection : ListSection
{
public WebviewSection()
{
if (!WebKit.Global.IsSupported) {
AddItem(($"{nameof(WebKit.WebView)}", new Label($"{typeof(WebView).Namespace} is not suported on your OS")));
return;
}
AddItem(ShowHtml());
AddItem(ShowJavaScript());
AddItem(ShowUri());
}
public (string, Widget) ShowHtml()
{
var webView = new WebView {
HeightRequest = 100,
WidthRequest = 400,
Hexpand = true
};
webView.LoadHtml($"This is a <b>{nameof(WebView)}</b> showing html text");
return ($"{nameof(WebView)} show html text:", webView);
}
public (string, Widget) ShowJavaScript()
{
var webView = new WebView {
HeightRequest = 100,
WidthRequest = 400,
Hexpand = true
};
webView.Settings.EnableDeveloperExtras = true;
var userContentManager = webView.UserContentManager;
var messageHandlerName = "gtksharp";
var script = new UserScript(
source: $"function testFunc() {{\n" +
$"window.webkit.messageHandlers.{messageHandlerName}.postMessage(\"postMessage\");\n" +
$"return 'Success' }};\n",
UserContentInjectedFrames.AllFrames,
UserScriptInjectionTime.Start, null, null);
userContentManager.AddScript(script);
var buttonClickPostMessage = $"var button = document.getElementById(\"clickMeButton\");\n" +
$"button.addEventListener(\"click\", " +
$"function() {{varmessageToPost = {{'ButtonId':'clickMeButton'}};\n" +
$"window.webkit.messageHandlers.{messageHandlerName}.postMessage(\"clickMeButton clicked\");\n}},false);";
var script2 = new UserScript(
source: buttonClickPostMessage,
UserContentInjectedFrames.AllFrames,
UserScriptInjectionTime.End, null, null);
userContentManager.AddScript(script2);
userContentManager.RegisterScriptMessageHandler(messageHandlerName);
userContentManager.ScriptMessageReceived += (o, args) => {
var value = args.JsResult?.JsValue;
if (value is { IsString: true } v)
ApplicationOutput.WriteLine($"{nameof(userContentManager.ScriptMessageReceived)}:\t{nameof(JavascriptResult.JsValue)}\t{v?.ToString()}");
};
webView.LoadHtml($"This is a <b>{nameof(WebView)}</b> with {nameof(UserScript)}" +
"<br/>Send message <input id=\"clickMeButton\" type=\"button\" value=\"Submit\" class=\"button\" onclick=\"\">");
webView.LoadChanged += (s, e) => {
ApplicationOutput.WriteLine(s, $"{e.LoadEvent}");
if (e.LoadEvent != LoadEvent.Finished)
return;
webView.RunJavascript("testFunc()", null, HandleJavaScriptResult);
};
void HandleJavaScriptResult(object source_object, IAsyncResult res)
{
if (source_object is not WebView view) return;
try {
JavascriptResult js_result = view.RunJavascriptFinish(res);
if (js_result.JsValue is { } jsValue) {
if (jsValue.IsString) {
ApplicationOutput.WriteLine($"{nameof(webView.RunJavascriptFinish)}:\t{nameof(JavascriptResult.JsValue)}\t{jsValue.ToString()}");
}
}
} catch (Exception exception) {
ApplicationOutput.WriteLine($"{nameof(webView.RunJavascriptFinish)} throws:\n{exception.Message}");
}
}
return ($"{nameof(WebView)} with {nameof(UserScript)}:", webView);
}
public (string, Widget) ShowUri()
{
var webView = new WebView {
WidthRequest = 400,
Vexpand = true,
Hexpand = true,
};
webView.LoadUri("https://github.com/GtkSharp/GtkSharp#readme");
return ($"{nameof(WebView)} show uri:", webView);
}
}
}