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
+ }
0 commit comments