Skip to content

Commit 69e4f41

Browse files
authored
First
1 parent 3ad762a commit 69e4f41

File tree

6 files changed

+235
-0
lines changed

6 files changed

+235
-0
lines changed

GtkTreeView.sln

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GtkTreeView", "GtkTreeView\GtkTreeView.csproj", "{4761FE89-4F29-4F52-B916-9FCC81B49E96}"
4+
EndProject
5+
Global
6+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7+
Debug|Any CPU = Debug|Any CPU
8+
Release|Any CPU = Release|Any CPU
9+
EndGlobalSection
10+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
11+
{4761FE89-4F29-4F52-B916-9FCC81B49E96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12+
{4761FE89-4F29-4F52-B916-9FCC81B49E96}.Debug|Any CPU.Build.0 = Debug|Any CPU
13+
{4761FE89-4F29-4F52-B916-9FCC81B49E96}.Release|Any CPU.ActiveCfg = Release|Any CPU
14+
{4761FE89-4F29-4F52-B916-9FCC81B49E96}.Release|Any CPU.Build.0 = Release|Any CPU
15+
EndGlobalSection
16+
EndGlobal

GtkTreeView/GtkTreeView.csproj

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>WinExe</OutputType>
5+
<TargetFramework>net7.0</TargetFramework>
6+
<LangVersion>default</LangVersion>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<None Remove="**\*.glade" />
11+
<EmbeddedResource Include="**\*.glade">
12+
<LogicalName>%(Filename)%(Extension)</LogicalName>
13+
</EmbeddedResource>
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<PackageReference Include="GtkSharp" Version="3.24.24.*" />
18+
</ItemGroup>
19+
20+
</Project>

GtkTreeView/MainWindow.cs

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using GLib;
2+
using Gtk;
3+
using Application = Gtk.Application;
4+
using UI = Gtk.Builder.ObjectAttribute;
5+
6+
namespace GtkTreeView
7+
{
8+
class MainWindow : Window
9+
{
10+
[UI] private TreeView MyTree = null;
11+
[UI] private TreeStore MyStore = null;
12+
[UI] private CellRendererToggle MyToggler = null;
13+
[UI] private TreeViewColumn NameColumn = null;
14+
15+
enum StoreColumn
16+
{
17+
Name = 0,
18+
CheckState = 1
19+
}
20+
enum CheckState
21+
{
22+
False = 0,
23+
True = 1,
24+
Inconsistent = 2
25+
}
26+
27+
public MainWindow() : this(new Builder("MainWindow.glade"))
28+
{
29+
}
30+
31+
private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("MainWindow"))
32+
{
33+
builder.Autoconnect(this);
34+
35+
var it1 = MyStore.AppendValues("Europe", (int)CheckState.False);
36+
var it2 = MyStore.AppendValues(it1, "England", (int)CheckState.False);
37+
var it3 = MyStore.AppendValues(it1, "France", (int)CheckState.False);
38+
var it4 = MyStore.AppendValues(it2, "London", (int)CheckState.False);
39+
var it5 = MyStore.AppendValues(it2, "Leicester", (int)CheckState.False);
40+
var it6 = MyStore.AppendValues(it3, "Paris", (int)CheckState.False);
41+
var it7 = MyStore.AppendValues(it3, "Nice", (int)CheckState.False);
42+
43+
NameColumn.SetCellDataFunc(MyToggler, ToggleStateFunction);
44+
MyTree.ExpandAll();
45+
MyToggler.Toggled += MyTogglerOnToggled;
46+
DeleteEvent += Window_DeleteEvent;
47+
}
48+
49+
private void ToggleStateFunction(TreeViewColumn tree_column, CellRenderer cell,
50+
ITreeModel tree_model, TreeIter iter)
51+
{
52+
var checkState = (CheckState)MyStore.GetValue(iter, (int)StoreColumn.CheckState);
53+
cell.SetProperty("active", new Value(checkState== CheckState.True));
54+
cell.SetProperty("inconsistent", new Value(checkState==CheckState.Inconsistent));
55+
}
56+
57+
private void MyTogglerOnToggled(object o, ToggledArgs args)
58+
{
59+
MyStore.GetIter(out var it, new TreePath(args.Path));
60+
61+
var checkState = (CheckState)MyStore.GetValue(it, (int)StoreColumn.CheckState);
62+
var newCheckState = checkState == CheckState.True ? CheckState.False : CheckState.True;
63+
MyStore.SetValue(it, (int)StoreColumn.CheckState, (int)newCheckState);
64+
65+
//Propagate down
66+
AssimilateDescendantsCheckState(it, newCheckState);
67+
68+
//Propagate up
69+
while(MyStore.IterParent(out var parent, it))
70+
{
71+
var s = CalculateCheckState(parent);
72+
MyStore.SetValue(parent, (int)StoreColumn.CheckState, (int)s);
73+
it = parent;
74+
}
75+
}
76+
77+
void AssimilateDescendantsCheckState(TreeIter it, CheckState state)
78+
{
79+
if (MyStore.IterHasChild(it))
80+
{
81+
MyStore.IterChildren(out var child, it);
82+
do
83+
{
84+
var childState = (CheckState)MyStore.GetValue(child, (int)StoreColumn.CheckState);
85+
if (childState != state)
86+
{
87+
MyStore.SetValue(child, (int)StoreColumn.CheckState, (int)state);
88+
AssimilateDescendantsCheckState(child, state);
89+
}
90+
}while (MyStore.IterNext(ref child));
91+
}
92+
}
93+
94+
CheckState CalculateCheckState(TreeIter it)
95+
{
96+
var num0 = 0;
97+
var num1 = 0;
98+
99+
MyStore.IterChildren(out var child, it);
100+
do
101+
{
102+
var checkState = (int)MyStore.GetValue(child, (int)StoreColumn.CheckState);
103+
switch (checkState)
104+
{
105+
case 0:
106+
num0++;
107+
break;
108+
case 1:
109+
num1++;
110+
break;
111+
case 2:
112+
return CheckState.Inconsistent;
113+
}
114+
115+
if (num0 > 0 && num1 > 0)
116+
return CheckState.Inconsistent;
117+
}while (MyStore.IterNext(ref child));
118+
119+
return num1 > 0? CheckState.True : CheckState.False;
120+
}
121+
122+
private void Window_DeleteEvent(object sender, DeleteEventArgs a)
123+
{
124+
Application.Quit();
125+
}
126+
}
127+
}

GtkTreeView/MainWindow.glade

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!-- Generated with glade 3.40.0 -->
3+
<interface>
4+
<requires lib="gtk+" version="3.18"/>
5+
<object class="GtkTreeStore" id="MyStore">
6+
<columns>
7+
<!-- column-name Name -->
8+
<column type="gchararray"/>
9+
<!-- column-name CheckState -->
10+
<column type="gint"/>
11+
</columns>
12+
</object>
13+
<object class="GtkWindow" id="MainWindow">
14+
<property name="can-focus">False</property>
15+
<property name="title" translatable="yes">Example Window</property>
16+
<property name="default-width">480</property>
17+
<property name="default-height">240</property>
18+
<child>
19+
<object class="GtkTreeView" id="MyTree">
20+
<property name="visible">True</property>
21+
<property name="can-focus">True</property>
22+
<property name="model">MyStore</property>
23+
<property name="enable-grid-lines">both</property>
24+
<child internal-child="selection">
25+
<object class="GtkTreeSelection"/>
26+
</child>
27+
<child>
28+
<object class="GtkTreeViewColumn" id="NameColumn">
29+
<property name="resizable">True</property>
30+
<property name="sizing">autosize</property>
31+
<property name="title" translatable="yes">Name</property>
32+
<property name="clickable">True</property>
33+
<property name="reorderable">True</property>
34+
<property name="sort-indicator">True</property>
35+
<child>
36+
<object class="GtkCellRendererToggle" id="MyToggler"/>
37+
</child>
38+
<child>
39+
<object class="GtkCellRendererText"/>
40+
<attributes>
41+
<attribute name="text">0</attribute>
42+
</attributes>
43+
</child>
44+
</object>
45+
</child>
46+
</object>
47+
</child>
48+
</object>
49+
</interface>

GtkTreeView/Program.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
using Gtk;
3+
4+
namespace GtkTreeView
5+
{
6+
class Program
7+
{
8+
[STAThread]
9+
public static void Main(string[] args)
10+
{
11+
Application.Init();
12+
13+
var app = new Application("org.GtkTreeView.GtkTreeView", GLib.ApplicationFlags.None);
14+
app.Register(GLib.Cancellable.Current);
15+
16+
var win = new MainWindow();
17+
app.AddWindow(win);
18+
19+
win.Show();
20+
Application.Run();
21+
}
22+
}
23+
}

demo.mp4

568 KB
Binary file not shown.

0 commit comments

Comments
 (0)