forked from Clancey/MonoDroid.Dialog
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathRootElement.cs
383 lines (340 loc) · 12.1 KB
/
RootElement.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Android.App;
using Android.Content;
using Android.Views;
using Android.Widget;
namespace Android.Dialog
{
public class RootElement : Element, IEnumerable<Section>, IDialogInterfaceOnClickListener
{
TextView _caption;
TextView _value;
internal Group _group;
public bool UnevenRows;
public Func<RootElement, View> _createOnSelected;
public event EventHandler RadioSelectionChanged;
/// <summary>
/// Initializes a RootSection with a caption
/// </summary>
/// <param name="caption">
/// The caption to render.
/// </param>
public RootElement(string caption)
: base(caption, Resource.Layout.dialog_root)
{
Sections = new List<Section>();
}
/// <summary>
/// Initializes a RootSection with a caption and a callback that will
/// create the nested UIViewController that is activated when the user
/// taps on the element.
/// </summary>
/// <param name="caption">The caption to render.</param>
/// <param name="createOnSelected">The <see cref="Func{TResult}"/> that creates a view to display when the element selected.</param>
public RootElement(string caption, Func<RootElement, View> createOnSelected)
: base(caption, Resource.Layout.dialog_root)
{
_createOnSelected = createOnSelected;
Sections = new List<Section>();
}
/// <summary>
/// Initializes a RootElement with a caption with a summary fetched from the specified section and leement
/// </summary>
/// <param name="caption">
/// The caption to render cref="System.String"/>
/// </param>
/// <param name="section">
/// The section that contains the element with the summary.
/// </param>
/// <param name="element">
/// The element index inside the section that contains the summary for this RootSection.
/// </param>
public RootElement(string caption, int section, int element)
: base(caption, Resource.Layout.dialog_root)
{
}
/// <summary>
/// Initializes a RootElement that renders the summary based on the radio settings of the contained elements.
/// </summary>
/// <param name="caption">
/// The caption to ender
/// </param>
/// <param name="group">
/// The group that contains the checkbox or radio information. This is used to display
/// the summary information when a RootElement is rendered inside a section.
/// </param>
public RootElement(string caption, Group group)
: base(caption, Resource.Layout.dialog_root)
{
_group = group;
if (_group is RadioGroup)
Click = (o, e) => SelectRadio();
}
/// <summary>
/// Single save point for a context, elements can get this context via GetContext() for navigation operations
/// </summary>
public Context Context { get; set; }
internal List<Section> Sections = new List<Section>();
public int Count
{
get
{
return Sections.Count;
}
}
public Section this[int idx]
{
get
{
return Sections[idx];
}
}
public event EventHandler ValueChanged;
private void HandleValueChangedEvent(object sender, EventArgs args)
{
if (ValueChanged != null)
ValueChanged(sender, args);
}
internal int IndexOf(Section target)
{
int idx = 0;
foreach (Section s in Sections)
{
if (s == target)
return idx;
idx++;
}
return -1;
}
internal void Prepare()
{
int current = 0;
foreach (var element in Sections.SelectMany(s => s))
{
var re = element as RadioElement;
if (re != null)
re.RadioIdx = current++;
if (UnevenRows == false && element is IElementSizing)
UnevenRows = true;
}
}
public override string Summary()
{
return GetSelectedValue();
}
/// <summary>
/// Adds a new section to this RootElement
/// </summary>
/// <param name="section">
/// The section to add, if the root is visible, the section is inserted with no animation
/// </param>
public void Add(Section section)
{
if (section == null)
return;
Sections.Add(section);
section.Parent = this;
section.ValueChanged += HandleValueChangedEvent;
}
//
// This makes things LINQ friendly; You can now create RootElements
// with an embedded LINQ expression, like this:
// new RootElement ("Title") {
// from x in names
// select new Section (x) { new StringElement ("Sample") }
//
public void Add(IEnumerable<Section> sections)
{
foreach (var s in sections)
Add(s);
}
/// <summary>
/// Inserts a new section into the RootElement
/// </summary>
/// <param name="idx">
/// The index where the section is added <see cref="System.Int32"/>
/// </param>
/// <param name="newSections">
/// A collection of <see cref="Section"/> to insert into this instance.
/// </param>
/// <remarks>
/// This inserts the specified list of sections (a params argument) into the
/// root using the specified animation.
/// </remarks>
public void Insert(int idx, params Section[] newSections)
{
if (idx < 0 || idx > Sections.Count)
return;
if (newSections == null)
return;
//if (Table != null)
// Table.BeginUpdates();
int pos = idx;
foreach (var s in newSections)
{
s.Parent = this;
s.ValueChanged += HandleValueChangedEvent;
Sections.Insert(pos++, s);
}
}
/// <summary>
/// Removes a section at a specified location
/// </summary>
public void RemoveAt(int idx)
{
if (idx < 0 || idx >= Sections.Count)
return;
Sections.RemoveAt(idx);
}
public void Remove(Section s)
{
if (s == null)
return;
int idx = Sections.IndexOf(s);
if (idx == -1)
return;
RemoveAt(idx);
}
public void Clear()
{
foreach (var s in Sections)
s.Dispose();
Sections = new List<Section>();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Context = null;
if (Sections == null)
return;
Clear();
Sections = null;
}
}
public override bool IsSelectable
{
get { return true; }
}
/// <summary>
/// The currently selected Radio item in the whole Root.
/// </summary>
public int RadioSelected
{
get
{
var radio = _group as RadioGroup;
if (radio != null)
return radio.Selected;
return -1;
}
set
{
var radio = _group as RadioGroup;
if (radio != null)
radio.Selected = value;
}
}
private string GetSelectedValue()
{
var radio = _group as RadioGroup;
if (radio == null)
return string.Empty;
int selected = radio.Selected;
int current = 0;
foreach (RadioElement e in Sections.SelectMany(s => s).OfType<RadioElement>())
{
if (current == selected)
return e.Summary();
current++;
}
return string.Empty;
}
public override View GetView(Context context, View convertView, ViewGroup parent)
{
Context = context;
View cell = new TextView(context) { TextSize = 16f, Text = Caption };
var radio = _group as RadioGroup;
if (radio != null)
{
var radioValue = GetSelectedValue();
cell = DroidResources.LoadStringElementLayout(context, convertView, parent, LayoutId, out _caption, out _value);
if (cell != null)
{
_caption.Text = Caption;
_value.Text = radioValue;
}
}
//else if (_group != null)
//{
// int count = 0;
// foreach (var s in Sections)
// {
// foreach (var e in s.Elements)
// {
// var ce = e as CheckboxElement;
// if (ce != null)
// {
// if (ce.Value)
// count++;
// continue;
// }
// var be = e as BoolElement;
// if (be == null) continue;
// if (be.Value)
// count++;
// }
// }
// cell.DetailTextLabel.Text = count.ToString();
//}
//else if (_summarySection != -1 && _summarySection < Sections.Count)
//{
// var s = Sections[_summarySection];
// if (summaryElement < s.Elements.Count)
// cell.DetailTextLabel.Text = s.Elements[summaryElement].Summary();
//}
//cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
return cell;
}
public void SelectRadio()
{
var dialog = new AlertDialog.Builder(Context);
dialog.SetSingleChoiceItems(Sections.SelectMany(s => s).OfType<RadioElement>().Select(e => e.Summary()).ToArray(), RadioSelected, this);
dialog.SetTitle(Caption);
dialog.SetNegativeButton("Cancel", this);
dialog.Create().Show();
}
void IDialogInterfaceOnClickListener.OnClick(IDialogInterface dialog, int which)
{
if (which >= 0 && RadioSelected != which)
{
RadioSelected = which;
var radioValue = GetSelectedValue();
_value.Text = radioValue;
if (RadioSelectionChanged != null)
RadioSelectionChanged(this, EventArgs.Empty);
}
dialog.Dismiss();
}
/// <summary>
/// Enumerator that returns all the sections in the RootElement.
/// </summary>
/// <returns>
/// A <see cref="IEnumerator"/>
/// </returns>
public IEnumerator<Section> GetEnumerator()
{
return Sections.GetEnumerator();
}
/// <summary>
/// Enumerator that returns all the sections in the RootElement.
/// </summary>
IEnumerator IEnumerable.GetEnumerator()
{
return Sections.GetEnumerator();
}
}
}