~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.MacDev/MonoDevelop.MacDev.PlistEditor/PListObject.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// 
2
 
// PObject.cs
3
 
//  
4
 
// Author:
5
 
//       Mike KrĆ¼ger <mkrueger@xamarin.com>
6
 
// 
7
 
// Copyright (c) 2011 Xamarin <http://xamarin.com>
8
 
// 
9
 
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
 
// of this software and associated documentation files (the "Software"), to deal
11
 
// in the Software without restriction, including without limitation the rights
12
 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 
// copies of the Software, and to permit persons to whom the Software is
14
 
// furnished to do so, subject to the following conditions:
15
 
// 
16
 
// The above copyright notice and this permission notice shall be included in
17
 
// all copies or substantial portions of the Software.
18
 
// 
19
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
 
// THE SOFTWARE.
26
 
 
27
 
using System;
28
 
using System.Collections.Generic;
29
 
using MonoDevelop.Core;
30
 
using System.Linq;
31
 
using MonoMac.Foundation;
32
 
using System.Runtime.InteropServices;
33
 
using Gtk;
34
 
using System.Text;
35
 
using MonoDevelop.Ide;
36
 
using System.IO;
37
 
using MonoMac.ObjCRuntime;
38
 
 
39
 
namespace MonoDevelop.MacDev.PlistEditor
40
 
{
41
 
        public abstract class PObject
42
 
        {
43
 
                static readonly IntPtr cls_NSPropertyListSerialization = Class.GetHandle ("NSPropertyListSerialization");
44
 
                static readonly IntPtr sel_dataFromPropertyList_format_options_error = Selector.GetHandle ("dataWithPropertyList:format:options:error:");
45
 
                                
46
 
                [DllImport (MonoMac.Constants.ObjectiveCLibrary, EntryPoint="objc_msgSend")]
47
 
                static extern IntPtr IntPtr_objc_msgSend_IntPtr_Int_Int_OutIntPtr (
48
 
                        IntPtr target,
49
 
                        IntPtr selector,
50
 
                        IntPtr arg0,
51
 
                        int arg1,
52
 
                        int arg2,
53
 
                        out IntPtr arg3);
54
 
                
55
 
                public static PObject Create (string type)
56
 
                {
57
 
                        switch (type) {
58
 
                        case "Array":
59
 
                                return new PArray ();
60
 
                        case "Dictionary":
61
 
                                return new PDictionary ();
62
 
                        case "Boolean":
63
 
                                return new PBoolean (true);
64
 
                        case "Data":
65
 
                                return new PData (new byte[0]);
66
 
                        case "Date":
67
 
                                return new PDate (DateTime.Now);
68
 
                        case "Number":
69
 
                                return new PNumber (0);
70
 
                        case "String":
71
 
                                return new PString ("");
72
 
                        }
73
 
                        LoggingService.LogError ("Unknown pobject type:" + type);
74
 
                        return new PString ("<error>");
75
 
                }
76
 
                
77
 
                                
78
 
                internal static IEnumerable<KeyValuePair<string, PObject>> ToEnumerable (PObject obj)
79
 
                {
80
 
                        if (obj is PDictionary) {
81
 
                                return (PDictionary) obj;
82
 
                        } else if (obj is PArray) {
83
 
                                return ((PArray) obj).Select (k => new KeyValuePair<string, PObject> (k is IPValueObject ? ((IPValueObject) k).Value.ToString () : null, k));
84
 
                        } else {
85
 
                                return Enumerable.Empty <KeyValuePair<string, PObject>> ();
86
 
                        }
87
 
                }
88
 
                
89
 
                
90
 
                PObject parent;
91
 
                public PObject Parent {
92
 
                        get {
93
 
                                return parent;
94
 
                        }
95
 
                        set {
96
 
                                if (parent != null && value != null)
97
 
                                        throw new NotSupportedException ("Already parented.");
98
 
                                this.parent = value;
99
 
                        }
100
 
                }
101
 
                
102
 
                public abstract string TypeString {
103
 
                        get;
104
 
                }
105
 
                
106
 
                public void Replace (PObject newObject)
107
 
                {
108
 
                        var p = Parent;
109
 
                        if (p is PDictionary) {
110
 
                                var dict = (PDictionary)p;
111
 
                                var key = dict.GetKey (this);
112
 
                                if (key == null)
113
 
                                        return;
114
 
                                Remove ();
115
 
                                dict[key] = newObject;
116
 
                        } else if (p is PArray) {
117
 
                                var arr = (PArray)p;
118
 
                                arr.Replace (this, newObject);
119
 
                        }
120
 
                }
121
 
                
122
 
                public string Key {
123
 
                        get {
124
 
                                if (Parent is PDictionary) {
125
 
                                        var dict = (PDictionary)Parent;
126
 
                                        if (dict.Any (p => p.Value == this)) {
127
 
                                                var pair = dict.First (p => p.Value == this);
128
 
                                                        return pair.Key;
129
 
                                        }
130
 
                                }
131
 
                                return null;
132
 
                        }
133
 
                }
134
 
                
135
 
                public void Remove ()
136
 
                {
137
 
                        if (Parent is PDictionary) {
138
 
                                var dict = (PDictionary)Parent;
139
 
                                dict.Remove (Key);
140
 
                        } else if (Parent is PArray) {
141
 
                                var arr = (PArray)Parent;
142
 
                                arr.Remove (this);
143
 
                        } else {
144
 
                                if (Parent == null)
145
 
                                        throw new InvalidOperationException ("Can't remove from null parent");
146
 
                                throw new InvalidOperationException ("Can't remove from parent " + Parent);
147
 
                        }
148
 
                }
149
 
                
150
 
                public abstract NSObject Convert ();
151
 
                
152
 
                public abstract void SetValue (string text);
153
 
                
154
 
                public static implicit operator PObject (string value)
155
 
                {
156
 
                        return new PString (value);
157
 
                }
158
 
                
159
 
                public static implicit operator PObject (int value)
160
 
                {
161
 
                        return new PNumber (value);
162
 
                }
163
 
                
164
 
                public static implicit operator PObject (bool value)
165
 
                {
166
 
                        return new PBoolean (value);
167
 
                }
168
 
                
169
 
                public static implicit operator PObject (DateTime value)
170
 
                {
171
 
                        return new PDate (value);
172
 
                }
173
 
                
174
 
                public static implicit operator PObject (byte[] value)
175
 
                {
176
 
                        return new PData (value);
177
 
                }
178
 
                
179
 
                protected virtual void OnChanged (EventArgs e)
180
 
                {
181
 
                        if (SuppressChangeEvents)
182
 
                                return;
183
 
                        
184
 
                        EventHandler handler = this.Changed;
185
 
                        if (handler != null)
186
 
                                handler (this, e);
187
 
                        
188
 
                        if (Parent != null)
189
 
                                Parent.OnChanged (e);
190
 
                }
191
 
                
192
 
                protected bool SuppressChangeEvents {
193
 
                        get; set;
194
 
                }
195
 
                
196
 
                public event EventHandler Changed;
197
 
                
198
 
                public string ToXml ()
199
 
                {
200
 
                        using (new NSAutoreleasePool ()) {
201
 
                                var errorPtr = IntPtr.Zero;
202
 
                                var pobject = Convert ();
203
 
                                
204
 
                                var nsDataPtr = IntPtr_objc_msgSend_IntPtr_Int_Int_OutIntPtr (
205
 
                                        cls_NSPropertyListSerialization,
206
 
                                        sel_dataFromPropertyList_format_options_error,
207
 
                                        pobject.Handle, (int) NSPropertyListFormat.Xml, 0, out errorPtr);
208
 
                                
209
 
                                if (errorPtr != IntPtr.Zero) {
210
 
                                        var error = (NSError) MonoMac.ObjCRuntime.Runtime.GetNSObject (errorPtr);
211
 
                                        throw new Exception (error.LocalizedDescription);
212
 
                                } else if (nsDataPtr == IntPtr.Zero) {
213
 
                                        throw new Exception ("Could not convert the NSDictionary to xml representation");       
214
 
                                } else {
215
 
                                        var nsData = (NSData) MonoMac.ObjCRuntime.Runtime.GetNSObject (nsDataPtr);
216
 
                                        return System.Text.Encoding.UTF8.GetString (nsData.ToArray ());
217
 
                                }
218
 
                        }
219
 
                }
220
 
        }
221
 
        
222
 
        public abstract class PObjectContainer : PObject
223
 
        {
224
 
                public abstract bool Reload (string fileName);
225
 
                public abstract void Save (string fileName);
226
 
        }
227
 
        
228
 
        public interface IPValueObject
229
 
        {
230
 
                object Value { get; set; }
231
 
        }
232
 
        
233
 
        public abstract class PValueObject<T> : PObject, IPValueObject
234
 
        {
235
 
                T val;
236
 
                public T Value {
237
 
                        get {
238
 
                                return val;
239
 
                        }
240
 
                        set {
241
 
                                val = value;
242
 
                                OnChanged (EventArgs.Empty);
243
 
                        }
244
 
                }
245
 
                
246
 
                object IPValueObject.Value {
247
 
                        get { return Value; }
248
 
                        set { Value = (T) value; }
249
 
                }
250
 
                
251
 
                public PValueObject (T value)
252
 
                {
253
 
                        this.Value = value;
254
 
                }
255
 
                
256
 
                public PValueObject ()
257
 
                {
258
 
                }
259
 
 
260
 
                public static implicit operator T (PValueObject<T> pObj)
261
 
                {
262
 
                        return pObj != null ? pObj.Value : default(T);
263
 
                }
264
 
        }
265
 
        
266
 
        public class PDictionary : PObjectContainer, IEnumerable<KeyValuePair<string, PObject>>
267
 
        {
268
 
                public const string Type = "Dictionary";
269
 
                Dictionary<string, PObject> dict;
270
 
                List<string> order;
271
 
                
272
 
                public override string TypeString {
273
 
                        get {
274
 
                                return Type;
275
 
                        }
276
 
                }
277
 
                
278
 
                public PObject this[string key] {
279
 
                        get {
280
 
                                return dict[key];
281
 
                        }
282
 
                        set {
283
 
                                PObject existing;
284
 
                                bool exists = dict.TryGetValue (key, out existing);
285
 
                                if (!exists)
286
 
                                        order.Add (key);
287
 
                                
288
 
                                dict[key] = value;
289
 
                                
290
 
                                if (exists)
291
 
                                        OnRemoved (new PObjectEventArgs (existing));
292
 
                                OnAdded (new PObjectEventArgs (value));
293
 
                        }
294
 
                }
295
 
                
296
 
                public EventHandler<PObjectEventArgs> Added;
297
 
                
298
 
                protected virtual void OnAdded (PObjectEventArgs e)
299
 
                {
300
 
                        e.PObject.Parent = this;
301
 
                        var handler = this.Added;
302
 
                        if (handler != null)
303
 
                                handler (this, e);
304
 
                        OnChanged (EventArgs.Empty);
305
 
                }
306
 
                
307
 
                public void Add (string key, PObject value)
308
 
                {
309
 
                        dict.Add (key, value);
310
 
                        order.Add (key);
311
 
                        OnAdded (new PObjectEventArgs (value));
312
 
                }
313
 
                
314
 
                public void InsertAfter (string keyBefore, string key, PObject value)
315
 
                {
316
 
                        dict.Add (key, value);
317
 
                        order.Insert (order.IndexOf (keyBefore) + 1, key);
318
 
                        OnAdded (new PObjectEventArgs (value));
319
 
                }
320
 
                
321
 
                public int Count {
322
 
                        get {
323
 
                                return dict.Count;
324
 
                        }
325
 
                }
326
 
                
327
 
                #region IEnumerable[KeyValuePair[System.String,PObject]] implementation
328
 
                public IEnumerator<KeyValuePair<string, PObject>> GetEnumerator ()
329
 
                {
330
 
                        foreach (var key in order)
331
 
                                yield return new KeyValuePair<string, PObject> (key, dict[key]);
332
 
                }
333
 
                #endregion
334
 
 
335
 
                #region IEnumerable implementation
336
 
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
337
 
                {
338
 
                        return GetEnumerator ();
339
 
                }
340
 
                #endregion
341
 
                
342
 
                public PDictionary ()
343
 
                {
344
 
                        dict = new Dictionary<string, PObject> ();
345
 
                        order = new List<string> ();
346
 
                }
347
 
 
348
 
                public bool ContainsKey (string name)
349
 
                {
350
 
                        return dict.ContainsKey (name);
351
 
                }
352
 
                
353
 
                public EventHandler<PObjectEventArgs> Removed;
354
 
                
355
 
                protected virtual void OnRemoved (PObjectEventArgs e)
356
 
                {
357
 
                        e.PObject.Parent = null;
358
 
                        var handler = this.Removed;
359
 
                        if (handler != null)
360
 
                                handler (this, e);
361
 
                        OnChanged (EventArgs.Empty);
362
 
                }
363
 
 
364
 
                public bool Remove (string key)
365
 
                {
366
 
                        PObject obj;
367
 
                        if (dict.TryGetValue (key, out obj)) {
368
 
                                dict.Remove (key);
369
 
                                order.Remove (key);
370
 
                                OnRemoved (new PObjectEventArgs (obj));
371
 
                                return true;
372
 
                        }
373
 
                        return false;
374
 
                }
375
 
 
376
 
                public bool ChangeKey (PObject obj, string newKey)
377
 
                {
378
 
                        return ChangeKey (obj, newKey, null);
379
 
                }
380
 
                
381
 
                public bool ChangeKey (PObject obj, string newKey, PObject newValue)
382
 
                {
383
 
                        var oldkey = GetKey (obj);
384
 
                        if (oldkey == null || dict.ContainsKey (newKey))
385
 
                                return false;
386
 
                        
387
 
                        dict.Remove (oldkey);
388
 
                        dict.Add (newKey, newValue ?? obj);
389
 
                        order[order.IndexOf (oldkey)] = newKey;
390
 
                        if (newValue != null) {
391
 
                                OnRemoved (new PObjectEventArgs (obj));
392
 
                                OnAdded (new PObjectEventArgs (newValue));
393
 
                        } else {
394
 
                                OnChanged (EventArgs.Empty);
395
 
                        }
396
 
                        return true;
397
 
                }
398
 
 
399
 
                public string GetKey (PObject obj)
400
 
                {
401
 
                        foreach (var pair in dict) {
402
 
                                if (pair.Value == obj)
403
 
                                        return pair.Key;
404
 
                        }
405
 
                        return null;
406
 
                }
407
 
                
408
 
                public T Get<T> (string key) where T : PObject
409
 
                {
410
 
                        PObject obj = null;
411
 
                        if (!dict.TryGetValue (key, out obj))
412
 
                                return default(T);
413
 
                        return (T)obj;
414
 
                }
415
 
                
416
 
                
417
 
                public bool TryGetValue<T> (string key, out T value) where T : PObject
418
 
                {
419
 
                        PObject obj = null;
420
 
                        if (!dict.TryGetValue (key, out obj)) {
421
 
                                value = default(T);
422
 
                                return false;
423
 
                        }
424
 
                        
425
 
                        if (!(obj is T)) {
426
 
                                value = default(T);
427
 
                                return false;
428
 
                        }
429
 
                        
430
 
                        value = (T)obj;
431
 
                        return true;
432
 
                }
433
 
 
434
 
                public override void SetValue (string text)
435
 
                {
436
 
                        throw new NotSupportedException ();
437
 
                }
438
 
                
439
 
                public override NSObject Convert ()
440
 
                {
441
 
                        List<NSObject> objs = new List<NSObject> ();
442
 
                        List<NSObject> keys = new List<NSObject> ();
443
 
                        
444
 
                        foreach (var key in order) {
445
 
                                var val = dict[key].Convert ();
446
 
                                objs.Add (val);
447
 
                                keys.Add (new NSString (key));
448
 
                        }
449
 
                        return NSDictionary.FromObjectsAndKeys (objs.ToArray (), keys.ToArray ());
450
 
                }
451
 
                
452
 
                public override  void Save (string fileName)
453
 
                {
454
 
                        using (new NSAutoreleasePool ()) {
455
 
                                var dict = (NSDictionary)Convert ();
456
 
                                dict.WriteToFile (fileName, false);
457
 
                        }
458
 
                }
459
 
                
460
 
                public static PDictionary Load (string fileName)
461
 
                {
462
 
                        using (new NSAutoreleasePool ()) {
463
 
                                var dict = NSDictionary.FromFile (fileName);
464
 
                                return (PDictionary)Conv (dict);
465
 
                        }
466
 
                }
467
 
                
468
 
                public override bool Reload (string fileName)
469
 
                {
470
 
                        if (string.IsNullOrEmpty (fileName))
471
 
                                throw new ArgumentNullException ("fileName");
472
 
                        var pool = new NSAutoreleasePool ();
473
 
                        SuppressChangeEvents = true;
474
 
                        try {
475
 
                                dict.Clear ();
476
 
                                order.Clear ();
477
 
                                var nsd = NSDictionary.FromFile (fileName);
478
 
                                if (nsd != null) {
479
 
                                        foreach (var pair in nsd) {
480
 
                                                string k = pair.Key.ToString ();
481
 
                                                this [k] = Conv (pair.Value);
482
 
                                        }
483
 
                                } else {
484
 
                                        return false;
485
 
                                }
486
 
                        } finally {
487
 
                                SuppressChangeEvents = false;
488
 
                                pool.Dispose ();
489
 
                        }
490
 
                        OnChanged (EventArgs.Empty);
491
 
                        return true;
492
 
                }
493
 
                
494
 
                static IntPtr selObjCType = MonoMac.ObjCRuntime.Selector.GetHandle ("objCType");
495
 
                internal static PObject Conv (NSObject val)
496
 
                {
497
 
                        if (val == null)
498
 
                                return null;
499
 
                        if (val is NSDictionary) {
500
 
                                var result = new PDictionary ();
501
 
                                foreach (var pair in (NSDictionary)val) {
502
 
                                        string k = pair.Key.ToString ();
503
 
                                        result[k] = Conv (pair.Value);
504
 
                                }
505
 
                                return result;
506
 
                        }
507
 
                        
508
 
                        if (val is NSArray) {
509
 
                                var result = new PArray ();
510
 
                                var arr = NSArray.ArrayFromHandle<NSObject> (((NSArray)val).Handle);
511
 
                                if (arr == null)
512
 
                                        return null;
513
 
                                foreach (var f in arr) {
514
 
                                        if (f != null)
515
 
                                                result.Add (Conv (f));
516
 
                                }
517
 
                                return result;
518
 
                        }
519
 
                        
520
 
                        if (val is NSString)
521
 
                                return ((NSString)val).ToString ();
522
 
                        if (val is NSNumber) {
523
 
                                var nr = (NSNumber)val;
524
 
                                var str = Marshal.PtrToStringAnsi (MonoMac.ObjCRuntime.Messaging.IntPtr_objc_msgSend (val.Handle, selObjCType));
525
 
                                if (str == "c" || str == "C" || str == "B")
526
 
                                        return nr.BoolValue;
527
 
                                return nr.Int32Value;
528
 
                        }
529
 
                        if (val is NSDate)
530
 
                                return PDate.referenceDate + TimeSpan.FromSeconds (((NSDate)val).SecondsSinceReferenceDate);
531
 
                        
532
 
                        if (val is NSData) {
533
 
                                var data = (NSData)val;
534
 
                                var bytes = new byte[data.Length];
535
 
                                Marshal.Copy (data.Bytes, bytes, 0, (int)data.Length);
536
 
                                return bytes;
537
 
                        }
538
 
                        
539
 
                        throw new NotSupportedException (val.ToString ());
540
 
                }
541
 
                
542
 
                public override string ToString ()
543
 
                {
544
 
                        return string.Format ("[PDictionary: Items={0}]", dict.Count);
545
 
                }
546
 
 
547
 
                public void SetString (string key, string value)
548
 
                {
549
 
                        var result = Get<PString> (key);
550
 
                        if (result == null) {
551
 
                                this[key] = result = new PString (value);
552
 
                                return;
553
 
                        }
554
 
                        result.Value = value;
555
 
                        OnChanged (EventArgs.Empty);
556
 
                }
557
 
                
558
 
                public PString GetString (string key)
559
 
                {
560
 
                        var result = Get<PString> (key);
561
 
                        if (result == null) {
562
 
                                this[key] = result = new PString ("");
563
 
                        }
564
 
                        return result;
565
 
                }
566
 
                
567
 
                public PArray GetArray (string key)
568
 
                {
569
 
                        var result = Get<PArray> (key);
570
 
                        if (result == null) {
571
 
                                this[key] = result = new PArray ();
572
 
                        }
573
 
                        return result;
574
 
                }
575
 
        }
576
 
        
577
 
        public class PArray : PObjectContainer, IEnumerable<PObject>
578
 
        {
579
 
                public const string Type = "Array";
580
 
                List<PObject> list;
581
 
                
582
 
                public override string TypeString {
583
 
                        get {
584
 
                                return Type;
585
 
                        }
586
 
                }
587
 
                
588
 
                public int Count {
589
 
                        get {
590
 
                                return list.Count;
591
 
                        }
592
 
                }
593
 
                
594
 
                public PObject this[int i] {
595
 
                        get {
596
 
                                return list[i];
597
 
                        }
598
 
                }
599
 
                
600
 
                public PArray ()
601
 
                {
602
 
                        list = new List<PObject> ();
603
 
                }
604
 
                
605
 
                public EventHandler<PObjectEventArgs> Added;
606
 
                
607
 
                protected virtual void OnAdded (PObjectEventArgs e)
608
 
                {
609
 
                        e.PObject.Parent = this;
610
 
                        if (SuppressChangeEvents)
611
 
                                return;
612
 
                        
613
 
                        var handler = this.Added;
614
 
                        if (handler != null)
615
 
                                handler (this, e);
616
 
                        OnChanged (EventArgs.Empty);
617
 
                }
618
 
                
619
 
                public override bool Reload (string fileName)
620
 
                {
621
 
                        if (string.IsNullOrEmpty (fileName))
622
 
                                throw new ArgumentNullException ("fileName");
623
 
                        var pool = new NSAutoreleasePool ();
624
 
                        SuppressChangeEvents = true;
625
 
                        try {
626
 
                                list.Clear ();
627
 
                                var nsa = NSArray.FromFile (fileName);
628
 
                                if (nsa != null) {
629
 
                                        var arr = NSArray.ArrayFromHandle<NSObject> (nsa.Handle);
630
 
                                        foreach (var f in arr) {
631
 
                                                Add (PDictionary.Conv (f));
632
 
                                        }
633
 
                                } else {
634
 
                                        return false;
635
 
                                }
636
 
                        } finally {
637
 
                                SuppressChangeEvents = false;
638
 
                                pool.Dispose ();
639
 
                        }
640
 
                        OnChanged (EventArgs.Empty);
641
 
                        return true;
642
 
                }
643
 
                
644
 
                public override void Save (string fileName)
645
 
                {
646
 
                        using (new NSAutoreleasePool ()) {
647
 
                                var arr = (NSArray)Convert ();
648
 
                                arr.WriteToFile (fileName, false);
649
 
                        }
650
 
                }
651
 
 
652
 
                public void Add (PObject obj)
653
 
                {
654
 
                        list.Add (obj);
655
 
                        OnAdded (new PObjectEventArgs (obj));
656
 
                }
657
 
 
658
 
                public void Replace (PObject oldObj, PObject newObject)
659
 
                {
660
 
                        for (int i = 0; i < Count; i++) {
661
 
                                if (list[i] == oldObj) {
662
 
                                        list[i] = newObject;
663
 
                                        OnRemoved (new PObjectEventArgs (oldObj));
664
 
                                        OnAdded (new PObjectEventArgs (newObject));
665
 
                                        break;
666
 
                                }
667
 
                        }
668
 
                }
669
 
                
670
 
                public EventHandler<PObjectEventArgs> Removed;
671
 
                
672
 
                protected virtual void OnRemoved (PObjectEventArgs e)
673
 
                {
674
 
                        e.PObject.Parent = null;
675
 
                        if (SuppressChangeEvents)
676
 
                                return;
677
 
                        
678
 
                        var handler = this.Removed;
679
 
                        if (handler != null)
680
 
                                handler (this, e);
681
 
                        OnChanged (EventArgs.Empty);
682
 
                }
683
 
                
684
 
                public void Remove (PObject obj)
685
 
                {
686
 
                        if (list.Remove (obj))
687
 
                                OnRemoved (new PObjectEventArgs (obj));
688
 
                }
689
 
 
690
 
                public void Clear ()
691
 
                {
692
 
                        list.Clear ();
693
 
                        OnChanged (EventArgs.Empty);
694
 
                }
695
 
                
696
 
                public override void SetValue (string text)
697
 
                {
698
 
                        throw new NotSupportedException ();
699
 
                }
700
 
                
701
 
                public override NSObject Convert ()
702
 
                {
703
 
                        return NSArray.FromNSObjects (list.Select (x => x.Convert ()).ToArray ());
704
 
                }
705
 
                
706
 
                public override string ToString ()
707
 
                {
708
 
                        return string.Format ("[PArray: Items={0}]", Count);
709
 
                }
710
 
                
711
 
                public void AssignStringList (string strList)
712
 
                {
713
 
                        SuppressChangeEvents = true;
714
 
                        try {
715
 
                                Clear ();
716
 
                                foreach (var item in strList.Split (',', ' ')) {
717
 
                                        if (string.IsNullOrEmpty (item))
718
 
                                                continue;
719
 
                                        Add (new PString (item));
720
 
                                }
721
 
                        } finally {
722
 
                                SuppressChangeEvents = false;
723
 
                                OnChanged (EventArgs.Empty);
724
 
                        }
725
 
                }
726
 
                
727
 
                public string ToStringList ()
728
 
                {
729
 
                        var sb = new StringBuilder ();
730
 
                        foreach (PString str in list.Where (o => o is PString)) {
731
 
                                if (sb.Length > 0)
732
 
                                        sb.Append (", ");
733
 
                                sb.Append (str);
734
 
                        }
735
 
                        return sb.ToString ();
736
 
                }
737
 
                
738
 
                #region IEnumerable[PObject] implementation
739
 
                public IEnumerator<PObject> GetEnumerator ()
740
 
                {
741
 
                        return list.GetEnumerator ();
742
 
                }
743
 
                #endregion
744
 
 
745
 
                #region IEnumerable implementation
746
 
                System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
747
 
                {
748
 
                        return ((System.Collections.IEnumerable)list).GetEnumerator ();
749
 
                }
750
 
                #endregion
751
 
        }
752
 
        
753
 
        public class PBoolean : PValueObject<bool>
754
 
        {
755
 
                public const string Yes = "Yes";
756
 
                public const string No = "No";
757
 
                
758
 
                public const string Type = "Boolean";
759
 
                
760
 
                public override string TypeString {
761
 
                        get {
762
 
                                return Type;
763
 
                        }
764
 
                }
765
 
                
766
 
                public PBoolean (bool value) : base(value)
767
 
                {
768
 
                }
769
 
                
770
 
                public override void SetValue (string text)
771
 
                {
772
 
                        if (text == Yes || text == GettextCatalog.GetString ("Yes"))
773
 
                                Value = true;
774
 
                        else if (text == No || text == GettextCatalog.GetString ("No"))
775
 
                                Value = false;
776
 
                }
777
 
                
778
 
                public override NSObject Convert ()
779
 
                {
780
 
                        return NSNumber.FromBoolean (Value);
781
 
                }
782
 
        }
783
 
        
784
 
        public class PData : PValueObject<byte[]>
785
 
        {
786
 
                public const string Type = "Data";
787
 
                static readonly byte[] Empty = new byte [0];
788
 
                
789
 
                public override string TypeString {
790
 
                        get {
791
 
                                return Type;
792
 
                        }
793
 
                }
794
 
                
795
 
                public override NSObject Convert ()
796
 
                {
797
 
                        // Work around a bug in NSData.FromArray as it cannot (currently) handle
798
 
                        // zero length arrays
799
 
                        if (Value.Length == 0)
800
 
                                return new NSData ();
801
 
                        else
802
 
                                return NSData.FromArray (Value);
803
 
                }
804
 
                
805
 
                public PData (byte[] value) : base(value ?? Empty)
806
 
                {
807
 
                }
808
 
                
809
 
                public override void SetValue (string text)
810
 
                {
811
 
                        throw new NotSupportedException ();
812
 
                }
813
 
        }
814
 
        
815
 
        public class PDate : PValueObject<DateTime>
816
 
        {
817
 
                public const string Type = "Date";
818
 
                internal static DateTime referenceDate = new DateTime (2001, 1, 1, 0, 0, 0, DateTimeKind.Utc);
819
 
                
820
 
                public override string TypeString {
821
 
                        get {
822
 
                                return Type;
823
 
                        }
824
 
                }
825
 
                
826
 
                public PDate (DateTime value) : base(value)
827
 
                {
828
 
                }
829
 
                
830
 
                public override void SetValue (string text)
831
 
                {
832
 
                        throw new NotImplementedException ();
833
 
                }
834
 
                
835
 
                public override NSObject Convert ()
836
 
                {
837
 
                        var secs = (Value - referenceDate).TotalSeconds;
838
 
                        return NSDate.FromTimeIntervalSinceReferenceDate (secs);
839
 
                }
840
 
        }
841
 
        
842
 
        public class PNumber : PValueObject<int>
843
 
        {
844
 
                public const string Type = "Number";
845
 
                
846
 
                public override string TypeString {
847
 
                        get {
848
 
                                return Type;
849
 
                        }
850
 
                }
851
 
                
852
 
                public PNumber (int value) : base(value)
853
 
                {
854
 
                }
855
 
                
856
 
                public override void SetValue (string text)
857
 
                {
858
 
                        int newValue;
859
 
                        if (int.TryParse (text, out newValue))
860
 
                                Value = newValue;
861
 
                }
862
 
 
863
 
                public override NSObject Convert ()
864
 
                {
865
 
                        return NSNumber.FromInt32 (Value);
866
 
                }
867
 
        }
868
 
        
869
 
        public class PString : PValueObject<string>
870
 
        {
871
 
                public const string Type = "String";
872
 
                
873
 
                public override string TypeString {
874
 
                        get {
875
 
                                return Type;
876
 
                        }
877
 
                }
878
 
                
879
 
                public PString (string value) : base(value)
880
 
                {
881
 
                        if (value == null)
882
 
                                throw new ArgumentNullException ("value");
883
 
                }
884
 
                
885
 
                public override void SetValue (string text)
886
 
                {
887
 
                        if (text == null)
888
 
                                throw new ArgumentNullException ("text");
889
 
                        Value = text;
890
 
                }
891
 
                
892
 
                public override NSObject Convert ()
893
 
                {
894
 
                        return new NSString (Value);
895
 
                }
896
 
        }
897
 
        
898
 
        [Serializable]
899
 
        public sealed class PObjectEventArgs : EventArgs
900
 
        {
901
 
                public PObject PObject {
902
 
                        get;
903
 
                        private set;
904
 
                }
905
 
                
906
 
                public PObjectEventArgs (PObject pObject)
907
 
                {
908
 
                        this.PObject = pObject;
909
 
                }
910
 
        }
911
 
}