555aa920b013a823c546e670321b2ad3729388e5
[pithos-ms-client] / trunk%2FPithos.Client.WPF%2FSelectiveSynch%2FDirectoryRecord.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 { _isChecked=value; }
177         }
178
179         public DirectoryRecord(ObjectInfo info)
180         {
181             ObjectInfo = info;
182         }
183
184
185 /*
186         public IEnumerable<DirectoryInfo> GetCheckedDirectories()
187         {
188             var q = from record in this
189                     where record.IsChecked==true
190                     select record.Info;
191             return q;
192         }
193 */
194
195 /*
196         public void SetSelections(StringCollection selections)
197         {
198             IsChecked=selections.Contains(Info.FullName);                
199             foreach (var children in Directories)
200             {
201                 children.SetSelections(selections);
202             }
203         }
204 */
205
206
207         public IEnumerator<DirectoryRecord> GetEnumerator()
208         {
209             yield return this;
210             foreach (var children in Directories)
211                 foreach (var info in children)
212                 {
213                     yield return info;
214                 }
215         }
216
217         IEnumerator IEnumerable.GetEnumerator()
218         {
219             return GetEnumerator();
220         }
221
222         public override int GetHashCode()
223         {
224             return ObjectInfo == null
225                        ? (Uri == null ? DisplayName.GetHashCode() : Uri.GetHashCode())
226                        : ObjectInfo.GetHashCode();
227         }
228
229         public override bool Equals(object obj)
230         {
231             if (!(obj is DirectoryRecord))
232                 return false;
233             var other = (DirectoryRecord)obj;
234             if (Uri != other.Uri)
235                 return false;
236             if (ObjectInfo== null ^ other.ObjectInfo== null)
237                 return false;
238
239             if (ObjectInfo!= null && !ObjectInfo.Equals(other.ObjectInfo))
240                 return false;
241             var thisEnum = GetEnumerator();
242             var otherEnum = other.GetEnumerator();
243             //Skipt the first item, it is the current node itself
244             thisEnum.MoveNext();
245             otherEnum.MoveNext();
246             while (true)
247             {
248                 var thisMove = thisEnum.MoveNext();
249                 var otherMove = otherEnum.MoveNext();
250
251                 if (thisMove ^ otherMove)
252                     return false;
253                 if (!thisMove)
254                     return true;
255
256                 if (!thisEnum.Current.Equals(otherEnum.Current))
257                     return false;
258             }
259         }
260     }
261 }