Modified to allow initial selection of all folders and containers
[pithos-ms-client] / trunk / Pithos.Client.WPF / SelectiveSynch / DirectoryRecord.cs
1 #region
2 /* -----------------------------------------------------------------------
3  * <copyright file="DirectoryRecord.cs" company="GRNet">
4  * 
5  * Copyright 2011-2012 GRNET S.A. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or
8  * without modification, are permitted provided that the following
9  * conditions are met:
10  *
11  *   1. Redistributions of source code must retain the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer.
14  *
15  *   2. Redistributions in binary form must reproduce the above
16  *      copyright notice, this list of conditions and the following
17  *      disclaimer in the documentation and/or other materials
18  *      provided with the distribution.
19  *
20  *
21  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * The views and conclusions contained in the software and
35  * documentation are those of the authors and should not be
36  * interpreted as representing official policies, either expressed
37  * or implied, of GRNET S.A.
38  * </copyright>
39  * -----------------------------------------------------------------------
40  */
41 #endregion
42 using System;
43 using System.Collections;
44 using System.Collections.Generic;
45 using System.Collections.Specialized;
46 using System.Diagnostics;
47 using System.IO;
48 using System.Linq;
49 using System.Text;
50 using Caliburn.Micro;
51 using Pithos.Client.WPF.Utils;
52 using Pithos.Core.Agents;
53 using Pithos.Interfaces;
54
55 namespace Pithos.Client.WPF.SelectiveSynch
56 {
57     [DebuggerDisplay("{Uri} : {IsChecked}")]
58     public class DirectoryRecord :PropertyChangedBase, IEnumerable<DirectoryRecord>
59     {
60         private ObjectInfo _objectInfo;
61         public ObjectInfo ObjectInfo
62         {
63             get { return _objectInfo; }
64             set
65             {
66                 _objectInfo = value;
67                 Uri = value.Uri;
68             }
69         }
70
71         public Uri Uri { get; set; }
72         //public DirectoryInfo LocalInfo { get; set; }
73
74         DirectoryRecord _parent;
75
76         public bool Added { get; set; }
77         public bool Removed { get; set; }
78
79         private bool? _isChecked=true;
80         #region IsChecked
81
82         /// <summary>
83         /// Gets/sets the state of the associated UI toggle (ex. CheckBox).
84         /// The return value is calculated based on the check state of all
85         /// child FooViewModels.  Setting this property to true or false
86         /// will set all children to the same check state, and setting it 
87         /// to any value will cause the parent to verify its check state.
88         /// </summary>
89         public bool? IsChecked
90         {
91             get { return _isChecked; }
92             set { this.SetIsChecked(value, true, true); }
93         }
94
95         void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
96         {
97             if (value == _isChecked)
98                 return;
99
100             _isChecked = value;
101
102             //If the value is null both Added and Removed should be False
103             Added = _isChecked??false;
104             Removed = !(_isChecked??true);
105
106             if (updateChildren && _isChecked.HasValue)
107                 this.Directories.Apply(c => c.SetIsChecked(_isChecked, true, false));
108
109             if (updateParent && _parent != null)
110                 _parent.VerifyCheckState();
111
112             this.RaisePropertyChangedEventImmediately("IsChecked");
113         }
114
115         void VerifyCheckState()
116         {
117             bool? state = null;
118             for (var i = 0; i < this.Directories.Count(); ++i)
119             {
120                 bool? current = this.Directories.ElementAt(i).IsChecked;
121                 if (i == 0)
122                 {
123                     state = current;
124                 }
125                 else if (state != current)
126                 {
127                     state = null;
128                     break;
129                 }
130             }
131             this.SetIsChecked(state, false, true);
132         }
133
134         #endregion // IsChecked
135
136
137         public bool IsInitiallySelected { get; private set; }
138
139         private List<DirectoryRecord>  _directories=new List<DirectoryRecord>();
140         public List<DirectoryRecord> Directories
141         {
142             get { return _directories; }
143             set { _directories= value; }
144         }
145
146         public DirectoryRecord()
147         {
148             
149 /*
150              _directories = new Lazy<List<DirectoryRecord>>(() => 
151                 new List<DirectoryRecord>());
152 */
153 /*
154              _directories = new Lazy<List<DirectoryRecord>>(() => 
155                 (from directory in Info.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
156                 where !directory.FullName.StartsWith(ignorePath)
157                 select new DirectoryRecord(ignorePath) { Info = directory }).ToList());
158 */
159         }
160
161         private string _displayName;
162
163         public string DisplayName
164         {
165             get
166             {
167                 if (ObjectInfo != null)
168                     return ObjectInfo.Name.Split('/').Last();
169                 return _displayName;
170             }
171             set { _displayName = value; }
172         }
173
174         public bool IsExplicitlyChecked
175         {
176             set\r
177             {\r
178                 _isChecked=value;\r
179                 this.RaisePropertyChangedEventImmediately("IsChecked");\r
180             }
181         }
182
183         public DirectoryRecord(ObjectInfo info)
184         {
185             ObjectInfo = info;
186         }
187
188
189 /*
190         public IEnumerable<DirectoryInfo> GetCheckedDirectories()
191         {
192             var q = from record in this
193                     where record.IsChecked==true
194                     select record.Info;
195             return q;
196         }
197 */
198
199 /*
200         public void SetSelections(StringCollection selections)
201         {
202             IsChecked=selections.Contains(Info.FullName);                
203             foreach (var children in Directories)
204             {
205                 children.SetSelections(selections);
206             }
207         }
208 */
209
210
211         public IEnumerator<DirectoryRecord> GetEnumerator()
212         {
213             yield return this;
214             foreach (var children in Directories)
215                 foreach (var info in children)
216                 {
217                     yield return info;
218                 }
219         }
220
221         IEnumerator IEnumerable.GetEnumerator()
222         {
223             return GetEnumerator();
224         }
225
226         public override int GetHashCode()
227         {
228             return ObjectInfo == null
229                        ? (Uri == null ? DisplayName.GetHashCode() : Uri.GetHashCode())
230                        : ObjectInfo.GetHashCode();
231         }
232
233         public override bool Equals(object obj)
234         {
235             if (!(obj is DirectoryRecord))
236                 return false;
237             var other = (DirectoryRecord)obj;
238             if (Uri != other.Uri)
239                 return false;
240             if (ObjectInfo== null ^ other.ObjectInfo== null)
241                 return false;
242
243             if (ObjectInfo!= null && !ObjectInfo.Equals(other.ObjectInfo))
244                 return false;
245             var thisEnum = GetEnumerator();
246             var otherEnum = other.GetEnumerator();
247             //Skipt the first item, it is the current node itself
248             thisEnum.MoveNext();
249             otherEnum.MoveNext();
250             while (true)
251             {
252                 var thisMove = thisEnum.MoveNext();
253                 var otherMove = otherEnum.MoveNext();
254
255                 if (thisMove ^ otherMove)
256                     return false;
257                 if (!thisMove)
258                     return true;
259
260                 if (!thisEnum.Current.Equals(otherEnum.Current))
261                     return false;
262             }
263         }
264     }
265 }