Mmmm.. rispostato l'aggiornamento della lista nel thread principale e non

Leonardo Robol [2010-02-16 16:38]
Mmmm.. rispostato l'aggiornamento della lista nel thread principale e non
dà più problemi ma non mi è chiaro il perché -.-
Filename
Dizzy/EventManager.cs
Dizzy/FileTreeView.cs
Dizzy/GlobalConfig.cs
Dizzy/MainWindow.cs
Dizzy/Protocol.cs
gtk-gui/Dizzy.AuthDialog.cs
gtk-gui/gui.stetic
diff --git a/Dizzy/EventManager.cs b/Dizzy/EventManager.cs
index b51c5e3..aa790d0 100644
--- a/Dizzy/EventManager.cs
+++ b/Dizzy/EventManager.cs
@@ -28,10 +28,8 @@ namespace Dizzy

 		// Gestione dei file e dei task. Questi devono essere inizializzati
 		// Appena sono creati.
-		public static FileTreeView fileTreeView = null;
-		public static TaskTreeView taskTreeView = null;
-		public static void RegisterFileTreeView (ref FileTreeView f) { fileTreeView = f; }
-		public static void RegisterTaskTreeView (ref TaskTreeView t) { taskTreeView = t; }
+		public static FileTreeView fileTreeView;
+		public static TaskTreeView taskTreeView;

 		public EventManager () {
 		}
@@ -76,19 +74,21 @@ namespace Dizzy
 		}

 		public static void AuthenticationRequired () {
-			GLib.Idle.Add (delegate {
-				Log.Info ("Uei, sembra che qualcuno mi abbia chiesto di autenticarsi!");
-				if (EventManager.authDialog == null)
-				{
-					EventManager.authDialog = new AuthDialog ();
-					EventManager.authDialog.Run ();
-					EventManager.authDialog.Destroy ();
-					EventManager.authDialog = null;
-					GlobalConfig.authenticated = true;
-				}
-				return false;
-			});
-
+			GLib.Idle.Add (delegate { return AuthenticationDialog (); });
+			WaitForAuthentication ();
+		}
+
+		public static bool AuthenticationDialog () {
+			Log.Info ("Uei, sembra che qualcuno mi abbia chiesto di autenticarsi!");
+			if (EventManager.authDialog == null)
+			{
+				EventManager.authDialog = new AuthDialog ();
+				EventManager.authDialog.Run ();
+				EventManager.authDialog.Destroy ();
+				EventManager.authDialog = null;
+				GlobalConfig.authenticated = true;
+			}
+			return false;
 		}

 		public static void WaitForAuthentication () {
@@ -150,7 +150,9 @@ namespace Dizzy
 		{
 			if (fileTreeView == null) { return; }
 			GLib.Idle.Add(delegate {
-				fileTreeView.AddFile (f);
+				lock(fileTreeView) {
+					fileTreeView.AddFile (f);
+				}
 				return false;
 			});
 		}
@@ -158,7 +160,9 @@ namespace Dizzy
 		public static void FileTreeViewClear() {
 			if (fileTreeView == null) { return; }
 			GLib.Idle.Add(delegate {
+				lock(fileTreeView) {
 				fileTreeView.Clear ();
+				}
 				return false;
 			});
 		}
@@ -168,7 +172,9 @@ namespace Dizzy
 			if (taskTreeView == null)
 				return;
 			GLib.Idle.Add (delegate {
+				lock(taskTreeView) {
 				EventManager.AddIter(GUID, taskTreeView.AddTask (filename, perc));
+				}
 				return false;
 			});

@@ -189,7 +195,9 @@ namespace Dizzy
 				return;
 			}
 			GLib.Idle.Add(delegate {
+				lock (taskTreeView) {
 				taskTreeView.SetProgress (iter, perc);
+				}
 				return false;
 			});
 		}
@@ -200,7 +208,8 @@ namespace Dizzy
 				return;
 			TreeIter iter = iters[GUID];
 			GLib.Idle.Add (delegate {
-				taskTreeView.DeleteRow (iter);
+				lock (taskTreeView) {
+				taskTreeView.DeleteRow (iter); }
 				return false;
 			});
 			iters.Remove (GUID);
diff --git a/Dizzy/FileTreeView.cs b/Dizzy/FileTreeView.cs
index 44c06cd..18ecc34 100644
--- a/Dizzy/FileTreeView.cs
+++ b/Dizzy/FileTreeView.cs
@@ -78,10 +78,12 @@ namespace Dizzy
 		{

 			// Aggiungo i valori effettivi nel liststore.
+			lock (fileListStore) {
 			fileListStore.AppendValues(	file.name,
 		    	                		file.user,
 		            		           	file.path,
 			                    		file.SizeToString ());
+			}

 		}

diff --git a/Dizzy/GlobalConfig.cs b/Dizzy/GlobalConfig.cs
index 6f64b0f..1170a10 100644
--- a/Dizzy/GlobalConfig.cs
+++ b/Dizzy/GlobalConfig.cs
@@ -9,7 +9,15 @@ namespace Dizzy
 	public static class GlobalConfig
 	{
 		public static string password;
-		public static bool authenticated;
+		private static bool _authenticated;
+		public static bool authenticated {
+			get {
+				lock(typeof(GlobalConfig)) { return _authenticated; }
+			}
+			set {
+				lock(typeof(GlobalConfig)) { _authenticated = value; }
+			}
+		}
 		private static SQLiteConnection conn;

 		private static string val;
@@ -25,7 +33,7 @@ namespace Dizzy
 		public static string GetValue(string field)
 		{

-		lock(typeof(GlobalConfig)) {
+		lock(conn) {
 				SQLiteCommand sqlCmd;
 				conn.Open ();
 				sqlCmd = conn.CreateCommand ();
@@ -43,7 +51,7 @@ namespace Dizzy

 		public static void InsertValue(string field, string val)
 		{
-			lock(typeof(GlobalConfig)) {
+			lock(conn) {
 				SQLiteCommand sqlCmd;

 				conn.Open ();
@@ -57,7 +65,7 @@ namespace Dizzy

 		private static void Init ()
 		{
-		lock(typeof(GlobalConfig)) {
+		lock(conn) {
 			SQLiteCommand sqlCmd;
 			conn.Open ();
 			sqlCmd = conn.CreateCommand ();
diff --git a/Dizzy/MainWindow.cs b/Dizzy/MainWindow.cs
index 701ba2c..07cf962 100644
--- a/Dizzy/MainWindow.cs
+++ b/Dizzy/MainWindow.cs
@@ -6,9 +6,6 @@ public partial class MainWindow : Gtk.Window
 {

 	Protocol protocol;
-	FileTreeView files;
-	TaskTreeView tasks;
-	AuthDialog a;

 	public MainWindow () : base(Gtk.WindowType.Toplevel)
 	{
@@ -17,12 +14,14 @@ public partial class MainWindow : Gtk.Window
 		GlobalConfig.authenticated = false;

 		// Inizializziamo la vista dei file.
-		files = new Dizzy.FileTreeView (filelist);
-		EventManager.RegisterFileTreeView (ref files);
+		/* files = new Dizzy.FileTreeView (filelist);
+		EventManager.RegisterFileTreeView (files); */
+		EventManager.fileTreeView = new Dizzy.FileTreeView (filelist);

 		// .. e anche quella dei download
-		tasks = new Dizzy.TaskTreeView (tasklist);
-		EventManager.RegisterTaskTreeView (ref tasks);
+		/* tasks = new Dizzy.TaskTreeView (tasklist);
+		EventManager.RegisterTaskTreeView (tasks); */
+		EventManager.taskTreeView = new Dizzy.TaskTreeView (tasklist);


 		// Carichiamo qualche impostazione di default
@@ -33,7 +32,6 @@ public partial class MainWindow : Gtk.Window


 		this.protocol = new Protocol ();
-		this.protocol.AuthenticationRequired += this.Connect;

 		Log.StatusBarUpdate += this.OnStatusBarUpdate;

@@ -42,20 +40,7 @@ public partial class MainWindow : Gtk.Window
 	public void OnStatusBarUpdate (string message)
 	{
 		dizzystatus.Push(0, message);
-	}
-
-
-	protected void Connect ()
-	{
-		if (this.a != null)
-			return;
-		this.a = new AuthDialog ();
-		a.Run ();
-		a.Destroy ();
-		a = null;
-
-	}
-
+	}

 	protected void OnDeleteEvent (object sender, DeleteEventArgs a)
 	{
@@ -80,14 +65,14 @@ public partial class MainWindow : Gtk.Window

 	protected void Search ()
 	{
-		this.files.Clear ();
+		EventManager.FileTreeViewClear ();
 		this.protocol.Search (searchBox.Text, searchUserBox.Text, typeBox.ActiveText);
 	}

 	protected virtual void OnRowActivated (object o, Gtk.RowActivatedArgs args)
 	{

-		File f = this.files.GetFileFromPath (args.Path);
+		File f = EventManager.fileTreeView.GetFileFromPath (args.Path);

 		string download_folder = this.downloadpathchooser.Filename;

@@ -132,7 +117,7 @@ public partial class MainWindow : Gtk.Window
 	{
 		// Dobbiamo determinare che trasferimento bloccare
 		TreePath path;
-		path = tasks.GetActivePath ();
+		path = EventManager.taskTreeView.GetActivePath ();
 		string GUID = EventManager.GetGUID (path);
 		this.protocol.DisconnectPath (GUID);
 	}
diff --git a/Dizzy/Protocol.cs b/Dizzy/Protocol.cs
index a979fb2..31b6ca9 100644
--- a/Dizzy/Protocol.cs
+++ b/Dizzy/Protocol.cs
@@ -36,14 +36,6 @@ namespace Dizzy
 		// Dati letti dal thread che cerca per capire cosa cercare
 		string keyword, user, type;

-
-		public delegate void ProtocolEvent ();
-
-		// Questo evento sembra non dare problemi perché ogni volta che
-		// è emesso aspettiamo che l'utente inserisca i dati necessari
-		// con while(!this.config.authenticated) {}
-		public event ProtocolEvent AuthenticationRequired;
-
 		public Protocol ()
 		{
 		}
@@ -118,35 +110,30 @@ namespace Dizzy
 			}


-			this.listUpdater = new Thread (new ThreadStart (this._UpdateFileList));
-			this.listUpdater.Start ();
-			// _UpdateFileList ();
+			// this.listUpdater = new Thread (new ThreadStart (this._UpdateFileList));
+			// this.listUpdater.Start ();
+			_UpdateFileList ();
 		}



 		protected void _UpdateFileList ()
 		{
+
 			// SFTPConnection s;
 			Sftp s;

 			if (!GlobalConfig.authenticated)
 			{
 				Log.Info ("I dati di autenticazione non sono presenti");
-				// this.AuthenticationRequired ();
-				EventManager.AuthenticationRequired ();

-				// Aspetto che l'utente abbia fatto.
-				while(!GlobalConfig.authenticated) {}
+				EventManager.AuthenticationDialog ();
+
 				Log.Info ("Ho acquisito utente e password");
 			}

 			EventManager.ListUpdateStarted ();

-			// Inizializziamo la connessione con i dati che supponiamo
-			// di avere.
-			// s = new SFTPConnection (this.config.GetValue("user"),
-			//                       	this.config.password);
 			s = new Sftp("poisson.phc.unipi.it", GlobalConfig.GetValue("user"),
 			             GlobalConfig.password);

@@ -158,20 +145,21 @@ namespace Dizzy
 				GlobalConfig.authenticated = false;
 			}

+
 			if(!GlobalConfig.authenticated)
 			{
 				EventManager.ErrorMessage ("Autenticazione fallita");
 			}
 			else
 			{
+				try {
+				lock(typeof(GlobalConfig)){
 				Log.Info ("Aggiornamento della lista avviato");
-
-				// s.Download (new File("/nobackup/robol/index.db", "robol"),
-				//	            this.config.ConfigDir ());
 				s.Get("/nobackup/robol/index.db", GlobalConfig.ListFileName());
-
 				Log.Info ("Lista Aggiornata");
 				s.Close ();
+				}}
+				catch (Exception e) { Log.Error ("Errore: " + e.Message); }
 			}
 			EventManager.ListUpdateFinished ();
 		}
@@ -207,10 +195,11 @@ namespace Dizzy
 		{
 			Log.Info ("Cominciamo il download di " + f.name);
 			// Preparo gli argomento da passare alla funzione.
+
 			if (!GlobalConfig.authenticated)
 			{
 				Log.Info ("Chiedo di effettuare l'autenticazione");
-				EventManager.AuthenticationRequired ();
+				EventManager.AuthenticationDialog ();
 			}


@@ -230,12 +219,8 @@ namespace Dizzy
 			// mi riesce di fare.
 			File f = (File) ((ArrayList) args)[0];
 			string downloadFolder = (string) ((ArrayList) args)[1];
-			Log.Info ("Avvio il download di " + f.name);
-
-			EventManager.WaitForAuthentication ();
-
-			Log.Info ("Bene, ora dovrei avere i dati!");

+
 			FileDownlad transfer;
 			try {
 				transfer = new FileDownlad (f, GlobalConfig.GetValue("user"), GlobalConfig.password, downloadFolder);
@@ -260,8 +245,8 @@ namespace Dizzy
 		{
 			// Preparo gli argomento da passare alla funzione.
 			if (!GlobalConfig.authenticated)
-				EventManager.AuthenticationRequired ();
-			while(!GlobalConfig.authenticated) {}
+				EventManager.AuthenticationDialog ();
+

 			ArrayList args = new ArrayList ();
 			args.Add (f);
diff --git a/gtk-gui/Dizzy.AuthDialog.cs b/gtk-gui/Dizzy.AuthDialog.cs
index d4bdd90..a657f08 100644
--- a/gtk-gui/Dizzy.AuthDialog.cs
+++ b/gtk-gui/Dizzy.AuthDialog.cs
@@ -17,6 +17,8 @@ namespace Dizzy {

         private Gtk.Label label3;

+        private Gtk.HSeparator hseparator1;
+
         private Gtk.Table table1;

         private Gtk.Label label1;
@@ -50,7 +52,7 @@ namespace Dizzy {
             // Container child vbox2.Gtk.Box+BoxChild
             this.label3 = new Gtk.Label();
             this.label3.Name = "label3";
-            this.label3.LabelProp = Mono.Unix.Catalog.GetString("Autenticazione su <b>poisson.phc.unipi.it</b>:");
+            this.label3.LabelProp = Mono.Unix.Catalog.GetString("L'operazione effettuata richiede l'inserimento di username e password\nper autenticarsi su <b>poisson.phc.unipi.it</b>.");
             this.label3.UseMarkup = true;
             this.vbox2.Add(this.label3);
             Gtk.Box.BoxChild w2 = ((Gtk.Box.BoxChild)(this.vbox2[this.label3]));
@@ -58,6 +60,14 @@ namespace Dizzy {
             w2.Expand = false;
             w2.Fill = false;
             // Container child vbox2.Gtk.Box+BoxChild
+            this.hseparator1 = new Gtk.HSeparator();
+            this.hseparator1.Name = "hseparator1";
+            this.vbox2.Add(this.hseparator1);
+            Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.vbox2[this.hseparator1]));
+            w3.Position = 1;
+            w3.Expand = false;
+            w3.Fill = false;
+            // Container child vbox2.Gtk.Box+BoxChild
             this.table1 = new Gtk.Table(((uint)(2)), ((uint)(2)), false);
             this.table1.Name = "table1";
             this.table1.RowSpacing = ((uint)(6));
@@ -67,19 +77,19 @@ namespace Dizzy {
             this.label1.Name = "label1";
             this.label1.LabelProp = Mono.Unix.Catalog.GetString("Username");
             this.table1.Add(this.label1);
-            Gtk.Table.TableChild w3 = ((Gtk.Table.TableChild)(this.table1[this.label1]));
-            w3.XOptions = ((Gtk.AttachOptions)(4));
-            w3.YOptions = ((Gtk.AttachOptions)(4));
+            Gtk.Table.TableChild w4 = ((Gtk.Table.TableChild)(this.table1[this.label1]));
+            w4.XOptions = ((Gtk.AttachOptions)(4));
+            w4.YOptions = ((Gtk.AttachOptions)(4));
             // Container child table1.Gtk.Table+TableChild
             this.label2 = new Gtk.Label();
             this.label2.Name = "label2";
             this.label2.LabelProp = Mono.Unix.Catalog.GetString("Password");
             this.table1.Add(this.label2);
-            Gtk.Table.TableChild w4 = ((Gtk.Table.TableChild)(this.table1[this.label2]));
-            w4.TopAttach = ((uint)(1));
-            w4.BottomAttach = ((uint)(2));
-            w4.XOptions = ((Gtk.AttachOptions)(4));
-            w4.YOptions = ((Gtk.AttachOptions)(4));
+            Gtk.Table.TableChild w5 = ((Gtk.Table.TableChild)(this.table1[this.label2]));
+            w5.TopAttach = ((uint)(1));
+            w5.BottomAttach = ((uint)(2));
+            w5.XOptions = ((Gtk.AttachOptions)(4));
+            w5.YOptions = ((Gtk.AttachOptions)(4));
             // Container child table1.Gtk.Table+TableChild
             this.passwordEntry = new Gtk.Entry();
             this.passwordEntry.CanFocus = true;
@@ -88,12 +98,12 @@ namespace Dizzy {
             this.passwordEntry.Visibility = false;
             this.passwordEntry.InvisibleChar = '•';
             this.table1.Add(this.passwordEntry);
-            Gtk.Table.TableChild w5 = ((Gtk.Table.TableChild)(this.table1[this.passwordEntry]));
-            w5.TopAttach = ((uint)(1));
-            w5.BottomAttach = ((uint)(2));
-            w5.LeftAttach = ((uint)(1));
-            w5.RightAttach = ((uint)(2));
-            w5.YOptions = ((Gtk.AttachOptions)(4));
+            Gtk.Table.TableChild w6 = ((Gtk.Table.TableChild)(this.table1[this.passwordEntry]));
+            w6.TopAttach = ((uint)(1));
+            w6.BottomAttach = ((uint)(2));
+            w6.LeftAttach = ((uint)(1));
+            w6.RightAttach = ((uint)(2));
+            w6.YOptions = ((Gtk.AttachOptions)(4));
             // Container child table1.Gtk.Table+TableChild
             this.userEntry = new Gtk.Entry();
             this.userEntry.CanFocus = true;
@@ -101,26 +111,26 @@ namespace Dizzy {
             this.userEntry.IsEditable = true;
             this.userEntry.InvisibleChar = '•';
             this.table1.Add(this.userEntry);
-            Gtk.Table.TableChild w6 = ((Gtk.Table.TableChild)(this.table1[this.userEntry]));
-            w6.LeftAttach = ((uint)(1));
-            w6.RightAttach = ((uint)(2));
-            w6.YOptions = ((Gtk.AttachOptions)(4));
+            Gtk.Table.TableChild w7 = ((Gtk.Table.TableChild)(this.table1[this.userEntry]));
+            w7.LeftAttach = ((uint)(1));
+            w7.RightAttach = ((uint)(2));
+            w7.YOptions = ((Gtk.AttachOptions)(4));
             this.vbox2.Add(this.table1);
-            Gtk.Box.BoxChild w7 = ((Gtk.Box.BoxChild)(this.vbox2[this.table1]));
-            w7.Position = 1;
-            w7.Expand = false;
-            w7.Fill = false;
-            w1.Add(this.vbox2);
-            Gtk.Box.BoxChild w8 = ((Gtk.Box.BoxChild)(w1[this.vbox2]));
-            w8.Position = 0;
+            Gtk.Box.BoxChild w8 = ((Gtk.Box.BoxChild)(this.vbox2[this.table1]));
+            w8.Position = 2;
             w8.Expand = false;
             w8.Fill = false;
+            w1.Add(this.vbox2);
+            Gtk.Box.BoxChild w9 = ((Gtk.Box.BoxChild)(w1[this.vbox2]));
+            w9.Position = 0;
+            w9.Expand = false;
+            w9.Fill = false;
             // Internal child Dizzy.AuthDialog.ActionArea
-            Gtk.HButtonBox w9 = this.ActionArea;
-            w9.Name = "dialog1_ActionArea";
-            w9.Spacing = 10;
-            w9.BorderWidth = ((uint)(5));
-            w9.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
+            Gtk.HButtonBox w10 = this.ActionArea;
+            w10.Name = "dialog1_ActionArea";
+            w10.Spacing = 10;
+            w10.BorderWidth = ((uint)(5));
+            w10.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
             // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
             this.buttonCancel = new Gtk.Button();
             this.buttonCancel.CanFocus = true;
@@ -129,9 +139,9 @@ namespace Dizzy {
             this.buttonCancel.UseUnderline = true;
             this.buttonCancel.Label = "gtk-cancel";
             this.AddActionWidget(this.buttonCancel, -6);
-            Gtk.ButtonBox.ButtonBoxChild w10 = ((Gtk.ButtonBox.ButtonBoxChild)(w9[this.buttonCancel]));
-            w10.Expand = false;
-            w10.Fill = false;
+            Gtk.ButtonBox.ButtonBoxChild w11 = ((Gtk.ButtonBox.ButtonBoxChild)(w10[this.buttonCancel]));
+            w11.Expand = false;
+            w11.Fill = false;
             // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
             this.buttonOk = new Gtk.Button();
             this.buttonOk.CanDefault = true;
@@ -141,15 +151,15 @@ namespace Dizzy {
             this.buttonOk.UseUnderline = true;
             this.buttonOk.Label = "gtk-ok";
             this.AddActionWidget(this.buttonOk, -5);
-            Gtk.ButtonBox.ButtonBoxChild w11 = ((Gtk.ButtonBox.ButtonBoxChild)(w9[this.buttonOk]));
-            w11.Position = 1;
-            w11.Expand = false;
-            w11.Fill = false;
+            Gtk.ButtonBox.ButtonBoxChild w12 = ((Gtk.ButtonBox.ButtonBoxChild)(w10[this.buttonOk]));
+            w12.Position = 1;
+            w12.Expand = false;
+            w12.Fill = false;
             if ((this.Child != null)) {
                 this.Child.ShowAll();
             }
-            this.DefaultWidth = 400;
-            this.DefaultHeight = 154;
+            this.DefaultWidth = 442;
+            this.DefaultHeight = 177;
             this.Show();
             this.userEntry.Activated += new System.EventHandler(this.OnUserEntryActivated);
             this.passwordEntry.Activated += new System.EventHandler(this.OnPasswordEntryActivated);
diff --git a/gtk-gui/gui.stetic b/gtk-gui/gui.stetic
index 02db08d..13e4012 100644
--- a/gtk-gui/gui.stetic
+++ b/gtk-gui/gui.stetic
@@ -545,7 +545,7 @@ Libro</property>
       </widget>
     </child>
   </widget>
-  <widget class="Gtk.Dialog" id="Dizzy.AuthDialog" design-size="400 154">
+  <widget class="Gtk.Dialog" id="Dizzy.AuthDialog" design-size="442 177">
     <property name="MemberName" />
     <property name="Title" translatable="yes">Autenticazione</property>
     <property name="Icon">stock:gtk-dialog-authentication Menu</property>
@@ -564,7 +564,8 @@ Libro</property>
             <child>
               <widget class="Gtk.Label" id="label3">
                 <property name="MemberName" />
-                <property name="LabelProp" translatable="yes">Autenticazione su &lt;b&gt;poisson.phc.unipi.it&lt;/b&gt;:</property>
+                <property name="LabelProp" translatable="yes">L'operazione effettuata richiede l'inserimento di username e password
+per autenticarsi su &lt;b&gt;poisson.phc.unipi.it&lt;/b&gt;.</property>
                 <property name="UseMarkup">True</property>
               </widget>
               <packing>
@@ -575,6 +576,17 @@ Libro</property>
               </packing>
             </child>
             <child>
+              <widget class="Gtk.HSeparator" id="hseparator1">
+                <property name="MemberName" />
+              </widget>
+              <packing>
+                <property name="Position">1</property>
+                <property name="AutoSize">True</property>
+                <property name="Expand">False</property>
+                <property name="Fill">False</property>
+              </packing>
+            </child>
+            <child>
               <widget class="Gtk.Table" id="table1">
                 <property name="MemberName" />
                 <property name="NRows">2</property>
@@ -664,7 +676,7 @@ Libro</property>
                 </child>
               </widget>
               <packing>
-                <property name="Position">1</property>
+                <property name="Position">2</property>
                 <property name="AutoSize">True</property>
                 <property name="Expand">False</property>
                 <property name="Fill">False</property>
ViewGit