forked from extnet/Ext.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAbstractContainer.cs
More file actions
1252 lines (1128 loc) · 51.2 KB
/
AbstractContainer.cs
File metadata and controls
1252 lines (1128 loc) · 51.2 KB
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
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/********
* @version : 2.1.1 - Ext.NET Pro License
* @author : Ext.NET, Inc. http://www.ext.net/
* @date : 2012-12-10
* @copyright : Copyright (c) 2007-2012, Ext.NET, Inc. (http://www.ext.net/). All rights reserved.
* @license : See license.txt and http://www.ext.net/license/.
********/
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ext.Net.Utilities;
namespace Ext.Net
{
/// <summary>
/// Base class for any Ext.Component that may contain other Components. Containers handle the basic behavior of containing items, namely adding, inserting and removing items.
/// The most commonly used Container classes are Ext.panel.Panel, Ext.window.Window and Ext.tab.Panel. If you do not need the capabilities offered by the aforementioned classes you can create a lightweight Container to be encapsulated by an HTML element to your specifications by using the autoEl config option.
///
/// Layout
/// Container classes delegate the rendering of child Components to a layout manager class which must be configured into the Container using the layout configuration property.
/// When either specifying child items of a Container, or dynamically adding Components to a Container, remember to consider how you wish the Container to arrange those child elements, and whether those child elements need to be sized using one of Ext's built-in layout schemes. By default, Containers use the Auto scheme which only renders child components, appending them one after the other inside the Container, and does not apply any sizing at all.
/// A common mistake is when a developer neglects to specify a layout (e.g. widgets like GridPanels or TreePanels are added to Containers for which no layout has been specified). If a Container is left to use the default Auto scheme, none of its child components will be resized, or changed in any way when the Container is resized.
/// Certain layout managers allow dynamic addition of child components. Those that do include Ext.layout.container.Card, Ext.layout.container.Anchor, Ext.layout.container.VBox, Ext.layout.container.HBox, and Ext.layout.container.Table.
/// Overnesting is a common problem. An example of overnesting occurs when a GridPanel is added to a TabPanel by wrapping the GridPanel inside a wrapping Panel (that has no layout specified) and then add that wrapping Panel to the TabPanel. The point to realize is that a GridPanel is a Component which can be added directly to a Container. If the wrapping Panel has no layout configuration, then the overnested GridPanel will not be sized as expected.
/// </summary>
[Meta]
[ParseChildren(true)]
[PersistChildren(false)]
[Description("An abstract base class which provides shared methods for Containers across the Sencha product line.")]
public abstract partial class AbstractContainer : ComponentBase, ILayout, IItems
{
/// <summary>
/// The height of this Anchor in pixels (defaults to auto).
/// If anchorSize is specifed, the anchor layout will use it as a virtual container for the purposes of calculating anchor measurements based on it instead, allowing the container to be sized independently of the anchoring logic if necessary.
/// </summary>
[Meta]
[DefaultValue(0)]
[NotifyParentProperty(true)]
[Description("The height of this Anchor in pixels (defaults to auto).")]
public virtual int AnchorHeight
{
get
{
return this.State.Get<int>("AnchorHeight", 0);
}
set
{
this.State.Set("AnchorHeight", value);
}
}
/// <summary>
/// The width of this Anchor in pixels (defaults to auto).
/// If anchorSize is specifed, the anchor layout will use it as a virtual container for the purposes of calculating anchor measurements based on it instead, allowing the container to be sized independently of the anchoring logic if necessary.
/// </summary>
[Meta]
[DefaultValue(0)]
[NotifyParentProperty(true)]
[Description("The width of this Anchor in pixels (defaults to auto).")]
public virtual int AnchorWidth
{
get
{
return this.State.Get<int>("AnchorWidth", 0);
}
set
{
this.State.Set("AnchorWidth", value);
}
}
/// <summary>
///
/// </summary>
[ConfigOption("anchorSize", JsonMode.Raw)]
[DefaultValue("")]
[Description("")]
protected virtual string AnchorSizeProxy
{
get
{
if (this.AnchorWidth == 0 && this.AnchorHeight == 0)
{
return "";
}
if (this.AnchorHeight == 0)
{
return this.AnchorWidth.ToString();
}
return JSON.Serialize(new { width = this.AnchorWidth, height = this.AnchorHeight });
}
}
/// <summary>
/// A string component id or the numeric index of the component that should be initially activated within the container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first item in the container's collection). activeItem only applies to layout styles that can display items one at a time (like Ext.layout.container.Card and Ext.layout.container.Fit)
/// </summary>
[Meta]
[ConfigOption]
[DirectEventUpdate(MethodName = "SetActiveItem")]
[Category("4. AbstractContainer")]
[DefaultValue("")]
[NotifyParentProperty(true)]
[Description("A string component id or the numeric index of the component that should be initially activated within the container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first item in the container's collection). activeItem only applies to layout styles that can display items one at a time (like Ext.layout.container.Card and Ext.layout.container.Fit)")]
public virtual string ActiveItem
{
get
{
return this.State.Get<string>("ActiveItem", "");
}
set
{
this.State.Set("ActiveItem", value);
}
}
/// <summary>
/// A string component id or the numeric index of the component that should be initially activated within the container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first item in the container's collection). activeItem only applies to layout styles that can display items one at a time (like Ext.layout.container.Card and Ext.layout.container.Fit)
/// </summary>
[Meta]
[ConfigOption("activeItem")]
[DirectEventUpdate(MethodName = "SetActiveIndex")]
[Category("4. AbstractContainer")]
[DefaultValue(-1)]
[NotifyParentProperty(true)]
[Description("A string component id or the numeric index of the component that should be initially activated within the container's layout on render. For example, activeItem: 'item-1' or activeItem: 0 (index 0 = the first item in the container's collection). activeItem only applies to layout styles that can display items one at a time (like Ext.layout.container.Card and Ext.layout.container.Fit)")]
public virtual int ActiveIndex
{
get
{
return this.State.Get<int>("ActiveIndex", -1);
}
set
{
this.State.Set("ActiveIndex", value);
}
}
/// <summary>
/// If true the container will automatically destroy any contained component that is removed from it, else destruction must be handled manually. Defaults to true.
/// </summary>
[Meta]
[ConfigOption]
[Category("4. AbstractContainer")]
[DefaultValue(true)]
[NotifyParentProperty(true)]
[Description("If true the container will automatically destroy any contained component that is removed from it, else destruction must be handled manually. Defaults to true.")]
public virtual bool AutoDestroy
{
get
{
return this.State.Get<bool>("AutoDestroy", true);
}
set
{
this.State.Set("AutoDestroy", value);
}
}
/// <summary>
/// If true .doLayout() is called after render. Default is false.
/// </summary>
[Meta]
[ConfigOption]
[Category("4. AbstractContainer")]
[DefaultValue(false)]
[NotifyParentProperty(true)]
[Description("If true .doLayout() is called after render. Default is false.")]
public virtual bool AutoDoLayout
{
get
{
return this.State.Get<bool>("AutoDoLayout", false);
}
set
{
this.State.Set("AutoDoLayout", value);
}
}
/// <summary>
/// An array of events that, when fired, should be bubbled to any parent container. See Ext.util.Observable-enableBubble. Defaults to ['add', 'remove'].
/// </summary>
[Meta]
[ConfigOption(typeof(StringArrayJsonConverter))]
[TypeConverter(typeof(StringArrayConverter))]
[Category("4. AbstractContainer")]
[DefaultValue(null)]
[Description("An array of events that, when fired, should be bubbled to any parent container. See Ext.util.Observable-enableBubble. Defaults to ['add', 'remove'].")]
public virtual string[] BubbleEvents
{
get
{
return this.State.Get<string[]>("BubbleEvents", null);
}
set
{
this.State.Set("BubbleEvents", value);
}
}
/// <summary>
/// The default xtype of child Components to create in this Container when a child item is specified as a raw configuration object, rather than as an instantiated AbstractComponent. Defaults to 'panel'.
/// </summary>
[Meta]
[ConfigOption]
[Category("4. AbstractContainer")]
[DefaultValue("panel")]
[NotifyParentProperty(true)]
[Description("The default xtype of child Components to create in this Container when a child item is specified as a raw configuration object, rather than as an instantiated AbstractComponent. Defaults to 'panel'.")]
public virtual string DefaultType
{
get
{
return this.State.Get<string>("DefaultType", "panel");
}
set
{
this.State.Set("DefaultType", value);
}
}
/// <summary>
/// A button is used after Enter is pressed. Can be ID, index or selector
/// </summary>
[Meta]
[DirectEventUpdate(GenerateMode=AutoGeneratingScript.Simple)]
[Category("4. AbstractContainer")]
[DefaultValue("")]
[TypeConverter(typeof(ButtonConverter))]
[NotifyParentProperty(true)]
[Description("A button is used after Enter is pressed. Can be ID, index or selector")]
public virtual string DefaultButton
{
get
{
return this.State.Get<string>("DefaultButton", "");
}
set
{
this.State.Set("DefaultButton", value);
}
}
/// <summary>
///
/// </summary>
[ConfigOption("defaultButton")]
[DefaultValue("")]
public virtual string DefaultButtonProxy
{
get
{
if (this.DefaultButton.IsEmpty())
{
return "";
}
ButtonBase btn = ControlUtils.FindControl<ButtonBase>(this, this.DefaultButton, true);
return btn != null ? btn.ConfigID : this.DefaultButton;
}
}
private ParameterCollection defaults;
/// <summary>
/// This option is a means of applying default settings to all added items whether added through the items config or via the add or insert methods.
/// If an added item is a config object, and not an instantiated AbstractComponent, then the default properties are unconditionally applied. If the added item is an instantiated AbstractComponent, then the default properties are applied conditionally so as not to override existing properties in the item.
/// If the defaults option is specified as a function, then the function will be called using this Container as the scope (this reference) and passing the added item as the first parameter. Any resulting object from that call is then applied to the item as default properties.
/// For example, to automatically apply padding to the body of each of a set of contained Ext.panel.Panel items, you could pass: defaults: {bodyStyle:'padding:15px'}.
/// </summary>
[Meta]
[ConfigOption(JsonMode.ArrayToObject)]
[Category("4. AbstractContainer")]
[NotifyParentProperty(true)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Description("This option is a means of applying default settings to all added items whether added through the items config or via the add or insert methods.")]
public virtual ParameterCollection Defaults
{
get
{
if (this.defaults == null)
{
this.defaults = new ParameterCollection(true) { Owner = this };
this.defaults.AfterItemAdd += Defaults_AfterItemAdd;
}
return this.defaults;
}
}
/// <summary>
///
/// </summary>
/// <param name="item"></param>
protected virtual void Defaults_AfterItemAdd(Parameter item)
{
item.CamelName = true;
}
/// <summary>
/// True to move any component to the detachedBody when the component is removed from this container. This option is only applicable when the component is not destroyed while being removed, see autoDestroy and remove. If this option is set to false, the DOM of the component will remain in the current place until it is explicitly moved. Defaults to: true
/// </summary>
[Meta]
[ConfigOption]
[Category("4. AbstractContainer")]
[DefaultValue(true)]
[NotifyParentProperty(true)]
[Description("True to move any component to the detachedBody when the component is removed from this container. This option is only applicable when the component is not destroyed while being removed, see autoDestroy and remove. If this option is set to false, the DOM of the component will remain in the current place until it is explicitly moved. Defaults to: true")]
public virtual bool DetachOnRemove
{
get
{
return this.State.Get<bool>("DetachOnRemove", true);
}
set
{
this.State.Set("DetachOnRemove", value);
}
}
/// <summary>
/// If true, suspend calls to doLayout. Usefule when batching multiple adds to a container and not passing them as multiple arguments or an array.
/// </summary>
[Meta]
[ConfigOption]
[Category("4. AbstractContainer")]
[DefaultValue(false)]
[NotifyParentProperty(true)]
[Description("If true, suspend calls to doLayout.")]
public virtual bool SuspendLayout
{
get
{
return this.State.Get<bool>("SuspendLayout", false);
}
set
{
this.State.Set("SuspendLayout", value);
}
}
/* Public Methods
-----------------------------------------------------------------------------------------------*/
/// <summary>
/// Adds Component(s) to this Container.
/// Description:
/// Fires the beforeadd event before adding.
/// The Container's default config values will be applied accordingly (see defaults for details).
/// Fires the add event after the component has been added.
/// Notes:
/// If the Container is already rendered when add is called, it will render the newly added Component into its content area.
///
/// If the Container was configured with a size-managing layout manager, the Container will recalculate its internal layout at this time too.
///
/// Note that the default layout manager simply renders child Components sequentially into the content area and thereafter performs no sizing.
/// </summary>
/// <param name="component">AbstractComponent to add to the container</param>
[Meta]
public virtual void Add(AbstractComponent component)
{
this.Items.Add(component);
}
/// <summary>
/// Adds Component(s) to this Container.
/// Description:
/// Fires the beforeadd event before adding.
/// The Container's default config values will be applied accordingly (see defaults for details).
/// Fires the add event after the component has been added.
/// Notes:
/// If the Container is already rendered when add is called, it will render the newly added Component into its content area.
///
/// If the Container was configured with a size-managing layout manager, the Container will recalculate its internal layout at this time too.
///
/// Note that the default layout manager simply renders child Components sequentially into the content area and thereafter performs no sizing.
/// </summary>
/// <param name="component">AbstractComponent to add to the container</param>
/// <param name="render">True to render component</param>
[Meta]
public virtual void Add(AbstractComponent component, bool render)
{
this.Add((component));
if (render)
{
component.Render();
}
}
/// <summary>
/// Adds a range of components to this container.
/// </summary>
[Meta]
public virtual void Add(IEnumerable<AbstractComponent> collection)
{
this.Items.AddRange(collection);
}
/// <summary>
/// Cascades down the component/container heirarchy from this component (passed in the first call), calling the specified function with each component.
/// </summary>
/// <param name="fn">The function to call</param>
public virtual void Cascade(JFunction fn)
{
this.Call("cascade", JRawValue.From(fn.ToScript()));
}
/// <summary>
/// Cascades down the component/container heirarchy from this component (passed in the first call), calling the specified function with each component.
/// </summary>
/// <param name="fn">The function to call</param>
/// <param name="scope">The scope of the function (defaults to current component)</param>
public virtual void Cascade(JFunction fn, string scope)
{
this.Call("cascade", JRawValue.From(fn.ToScript()), JRawValue.From(scope));
}
/// <summary>
/// Manually force this container's layout to be recalculated. The framework uses this internally to refresh layouts form most cases.
/// </summary>
[Meta]
public virtual void DoLayout()
{
this.Call("doLayout");
}
/// <summary>
/// Inserts a AbstractComponent into this Container at a specified index. Fires the beforeadd event before inserting, then fires the add event after the AbstractComponent has been inserted.
/// </summary>
/// <param name="index">The index at which the AbstractComponent will be inserted into the Container's items collection</param>
/// <param name="component">The child AbstractComponent to insert.</param>
[Meta]
public virtual void Insert(int index, AbstractComponent component)
{
this.Call("insert", index, new JRawValue(component.ClientID));
}
/// <summary>
/// Inserts a AbstractComponent into this Container at a specified index. Fires the beforeadd event before inserting, then fires the add event after the AbstractComponent has been inserted.
/// Ext uses lazy rendering, and will only render the inserted Component should it become necessary.
/// A Component config object may be passed in order to avoid the overhead of constructing a real Component object if lazy rendering might mean that the inserted Component will not be rendered immediately. To take advantage of this 'lazy instantiation', set the Ext.Component.xtype config property to the registered type of the Component wanted.
/// </summary>
/// <param name="index">The index at which the AbstractComponent will be inserted into the Container's items collection</param>
/// <param name="component">The child AbstractComponent to insert.</param>
/// <param name="render">True to render component</param>
[Meta]
public virtual void Insert(int index, AbstractComponent component, bool render)
{
if (render)
{
component.InsertTo(index, this);
}
else
{
this.Call("insert", index, new JRawValue(component.ClientID));
}
}
/// <summary>
/// Inserts a AbstractComponent into this Container at a specified index. Fires the beforeadd event before inserting, then fires the add event after the AbstractComponent has been inserted.
/// </summary>
/// <param name="index">The index at which the AbstractComponent will be inserted into the Container's items collection</param>
/// <param name="id">The id of the child AbstractComponent to insert.</param>
[Meta]
public virtual void Insert(int index, string id)
{
this.Call("insert", index, new JRawValue(id));
}
/// <summary>
/// Moves a AbstractComponent within the Container
/// </summary>
/// <param name="fromIdx">The index the AbstractComponent you wish to move is currently at.</param>
/// <param name="toIdx">The new index for the AbstractComponent.</param>
[Meta]
public virtual void Move(int fromIdx, int toIdx)
{
this.Call("move", fromIdx, toIdx);
}
/// <summary>
///Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.
/// </summary>
/// <param name="component">The component reference or id to remove.</param>
[Meta]
public virtual void Remove(AbstractComponent component)
{
this.Call("remove", new JRawValue(component.ClientID));
}
/// <summary>
/// Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.
/// </summary>
/// <param name="component">The component reference or id to remove.</param>
/// <param name="autoDestroy">(optional) True to automatically invoke the removed AbstractComponent's Ext.AbstractComponent-destroy function. Defaults to the value of this Container's autoDestroy config.</param>
[Meta]
[Description("Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.")]
public virtual void Remove(AbstractComponent component, bool autoDestroy)
{
this.Call("remove", new JRawValue(component.ClientID), autoDestroy);
}
/// <summary>
///Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.
/// </summary>
/// <param name="id">The component reference or id to remove.</param>
[Meta]
[Description("Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.")]
public virtual void Remove(string id)
{
this.Call("remove", new JRawValue(id));
}
/// <summary>
/// Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.
/// </summary>
/// <param name="id">The component reference or id to remove.</param>
/// <param name="autoDestroy">(optional) True to automatically invoke the removed AbstractComponent's Ext.AbstractComponent-destroy function. Defaults to the value of this Container's autoDestroy config.</param>
[Meta]
[Description("Removes a component from this container. Fires the beforeremove event before removing, then fires the remove event after the component has been removed.")]
public virtual void Remove(string id, bool autoDestroy)
{
this.Call("remove", new JRawValue(id), autoDestroy);
}
/// <summary>
/// Removes all components from this container.
/// </summary>
[Meta]
[Description("Removes all components from this container.")]
public virtual void RemoveAll()
{
this.Call("removeAll");
}
/// <summary>
/// Removes all components from this container.
/// </summary>
/// <param name="autoDestroy">(optional) True to automatically invoke the removed AbstractComponent's Ext.AbstractComponent.destroy function. Defaults to the value of this Container's autoDestroy config.</param>
[Meta]
[Description("Removes all components from this container.")]
public virtual void RemoveAll(bool autoDestroy)
{
this.Call("removeAll", autoDestroy);
}
/// <summary>
///
/// </summary>
[Description("")]
protected virtual void SetActiveIndex(int index)
{
this.AddScript("if ({0}.getLayout().setActiveItem){{{0}.getLayout().setActiveItem({1});}}", this.ClientID, index);
}
/// <summary>
///
/// </summary>
[Description("")]
protected virtual void SetActiveItem(string item)
{
this.AddScript("if ({0}.getLayout().setActiveItem){{{0}.getLayout().setActiveItem(\"{1}\");}}", this.ClientID, item);
}
///<summary>
/// Sets the active (visible) component in the layout to the next card, optional wrap parameter to wrap to the first card when the end of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
///<param name="wrap">Wrap to the first card when the end of the stack is reached.</param>
public virtual void NextItem(AnimConfig anim, bool wrap)
{
this.Call("layout.next", new JRawValue(new ClientConfig().Serialize(anim, true)), wrap);
}
///<summary>
/// Sets the active (visible) component in the layout to the next card, optional wrap parameter to wrap to the first card when the end of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
///<param name="wrap">Wrap to the first card when the end of the stack is reached.</param>
public virtual void NextItem(bool anim, bool wrap)
{
this.Call("layout.next", anim, wrap);
}
///<summary>
/// Sets the active (visible) component in the layout to the next card, optional wrap parameter to wrap to the first card when the end of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
public virtual void NextItem(AnimConfig anim)
{
this.Call("layout.next", new JRawValue(new ClientConfig().Serialize(anim, true)));
}
///<summary>
/// Sets the active (visible) component in the layout to the next card, optional wrap parameter to wrap to the first card when the end of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
public virtual void NextItem(bool anim)
{
this.Call("layout.next", anim);
}
///<summary>
/// Sets the active (visible) component in the layout to the next card, optional wrap parameter to wrap to the first card when the end of the stack is reached.
///</summary>
public virtual void NextItem()
{
this.Call("layout.next");
}
///<summary>
/// Sets the active (visible) component in the layout to the previous card, optional wrap parameter to wrap to the last card when the beginning of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
///<param name="wrap">Wrap to the last card when the start of the stack is reached.</param>
public virtual void PrevItem(AnimConfig anim, bool wrap)
{
this.Call("layout.prev", new JRawValue(new ClientConfig().Serialize(anim, true)), wrap);
}
///<summary>
/// Sets the active (visible) component in the layout to the previous card, optional wrap parameter to wrap to the last card when the beginning of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
///<param name="wrap">Wrap to the last card when the start of the stack is reached.</param>
public virtual void PrevItem(bool anim, bool wrap)
{
this.Call("layout.prev", anim, wrap);
}
///<summary>
/// Sets the active (visible) component in the layout to the previous card, optional wrap parameter to wrap to the last card when the beginning of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
public virtual void PrevItem(AnimConfig anim)
{
this.Call("layout.prev", new JRawValue(new ClientConfig().Serialize(anim, true)));
}
///<summary>
/// Sets the active (visible) component in the layout to the previous card, optional wrap parameter to wrap to the last card when the beginning of the stack is reached.
///</summary>
///<param name="anim">Animation to use for the card transition</param>
public virtual void PrevItem(bool anim)
{
this.Call("layout.prev", anim);
}
///<summary>
/// Sets the active (visible) component in the layout to the previous card, optional wrap parameter to wrap to the last card when the beginning of the stack is reached.
///</summary>
public virtual void PrevItem()
{
this.Call("layout.prev");
}
/* Items
-----------------------------------------------------------------------------------------------*/
internal string ItemsToRender
{
get;
set;
}
internal List<string> IDSToRender
{
get;
set;
}
private ItemsCollection<AbstractComponent> items;
/// <summary>
/// A single item, or an array of child Components to be added to this container
///
/// Unless configured with a layout, a Container simply renders child Components serially into its encapsulating element and performs no sizing or positioning upon them.
///
/// Example:
///
/// // specifying a single item
/// items: {...},
/// layout: 'fit', // The single items is sized to fit
///
/// // specifying multiple items
/// items: [{...}, {...}],
/// layout: 'hbox', // The items are arranged horizontally
/// Each item may be:
///
/// A AbstractComponent
/// A AbstractComponent configuration object
/// If a configuration object is specified, the actual type of AbstractComponent to be instantiated my be indicated by using the xtype option.
///
/// Every AbstractComponent class has its own xtype.
///
/// If an xtype is not explicitly specified, the defaultType for the Container is used, which by default is usually panel.
///
/// Notes:
///
/// Ext uses lazy rendering. Child Components will only be rendered should it become necessary. Items are automatically laid out when they are first shown (no sizing is done while hidden), or in response to a doLayout call.
///
/// Do not specify contentEl or html with items.
/// </summary>
[DeferredRender]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Description("A single item, or an array of child Components to be added to this container")]
public virtual ItemsCollection<AbstractComponent> Items
{
get
{
this.InitItems();
return this.items;
}
}
IList IItems.ItemsList
{
get
{
return this.ItemsProxy;
}
}
/// <summary>
/// Items Collection
/// </summary>
[ConfigOption("items", typeof(ItemCollectionJsonConverter))]
[DeferredRender]
[DefaultValue(null)]
[Description("Items Collection")]
protected virtual ItemsCollection<AbstractComponent> ItemsProxy
{
get
{
this.InitItems();
if (this.Items.Count == 0 && this.Layout.IsNotEmpty())
{
ControlCollection contentControls = ((IContent)this).ContentControls;
if (contentControls.Count == 0)
{
return this.items;
}
ItemsCollection<AbstractComponent> contentItems = new ItemsCollection<AbstractComponent>();
this.PopulateItems(contentControls, contentItems);
return contentItems;
}
ItemsCollection<AbstractComponent> realItems = new ItemsCollection<AbstractComponent>();
foreach (AbstractComponent cmp in this.items)
{
if (cmp is UserControlLoader)
{
realItems.AddRange(((UserControlLoader)cmp).Components);
}
else
{
realItems.Add(cmp);
}
}
return realItems;
}
}
/// <summary>
///
/// </summary>
[DefaultValue("")]
[ConfigOption("items", JsonMode.Raw)]
protected virtual string ItemsToRenderProxy
{
get
{
if (this.ItemsToRender.IsNotEmpty())
{
if (this.Items.Count > 0)
{
throw new Exception("Items cannot be used if items are rendered as section or page");
}
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (string item in this.IDSToRender)
{
sb.Append(Transformer.NET.Net.CreateToken(typeof(Transformer.NET.AnchorTag), new Dictionary<string, string>{
{"id", item}
}));
sb.Append(",");
}
if (this.IDSToRender.Count > 0)
{
sb.Remove(sb.Length - 1, 1);
}
sb.Append("]");
return sb.ToString();
}
return "";
}
}
/// <summary>
///
/// </summary>
/// <param name="contentControls"></param>
/// <param name="contentItems"></param>
protected virtual void PopulateItems(ControlCollection contentControls, ItemsCollection<AbstractComponent> contentItems)
{
foreach (Control control in contentControls)
{
AbstractComponent cmp = control as AbstractComponent;
if (cmp != null)
{
contentItems.Add(cmp);
cmp.ID = cmp.ID;
}
else if (control is ContentPlaceHolder || control is UserControl)
{
this.PopulateItems(control.Controls, contentItems);
}
else if(control is LiteralControl || control is Literal)
{
continue;
}
else
{
throw new Exception(string.Format(ServiceMessages.NON_LAYOUT_CONTROL, control.GetType().ToString()));
}
}
}
/// <summary>
///
/// </summary>
[Description("")]
protected void InitItems()
{
if (this.items == null)
{
this.items = new ItemsCollection<AbstractComponent>();
this.items.BeforeItemAdd += this.BeforeItemAdd;
this.items.AfterItemAdd += this.AfterItemAdd;
this.items.AfterItemRemove += this.AfterItemRemove;
this.items.SingleItemMode = this.SingleItemMode;
}
}
private bool layoutDetected;
/// <summary>
///
/// </summary>
[Description("")]
protected internal virtual void DetectLayoutFromConfig()
{
if (!this.layoutDetected && this.LayoutConfig.Count > 0)
{
string layoutConfig = this.LayoutConfig.Primary.GetType().Name.LeftOf("LayoutConfig").ToLowerInvariant();
if (this.Layout.IsNotEmpty() && this.State["Layout"] != null)
{
string layout = this.Layout.ToLowerInvariant();
layout = layout.EndsWith("layout") ? layout.LeftOfRightmostOf("layout") : layout;
if (layoutConfig != layout)
{
throw new Exception(ServiceMessages.LAYOUT_AMBIGUITY);
}
}
this.Layout = layoutConfig;
this.layoutDetected = true;
}
}
/// <summary>
///
/// </summary>
[Description("")]
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
}
/// <summary>
///
/// </summary>
[Description("")]
protected virtual void BeforeItemAdd(AbstractComponent item) { }
/// <summary>
///
/// </summary>
protected override bool PreventContent
{
get
{
bool result = base.PreventContent;
if (result)
{
return true;
}
if (this.Loader != null && this.Loader.Url.IsNotEmpty())
{
return true;
}
this.DetectLayoutFromConfig();
if (this.Layout.IsNotEmpty() && this.ContentControls.Count == 0)
{
return true;
}
return false;
}
}
/// <summary>
///
/// </summary>
protected internal override bool IsDeferredRender
{
get
{
//if (this.Visible && this.ParentComponent is TabPanel)
//{
// var tp = (TabPanel)this.ParentComponent;
// if (tp.AutoPostBack && tp.DeferredRender && tp.Items[tp.ActiveTabIndex].ID != this.ID)
// {
// this.ContentContainer.Visible = false;
// this.Items.Each(component => component.Visible = false);
// return true;
// }
// this.Items.Each(component => component.Visible = true);
// this.ContentContainer.Visible = true;
//}
return false;
}
}
/* TabPanel specific properties/methods
-----------------------------------------------------------------------------------------------*/
private MenuCollection tabMenu;
/// <summary>
/// Tab's menu
/// </summary>
[Meta]
[ConfigOption("tabMenu", typeof(SingleItemCollectionJsonConverter))]
[Category("4. AbstractContainer")]
[PersistenceMode(PersistenceMode.InnerProperty)]
[NotifyParentProperty(true)]
[Description("Tab's menu")]
public virtual MenuCollection TabMenu
{
get
{
if (this.tabMenu == null)
{
this.tabMenu = new MenuCollection();
this.tabMenu.AfterItemAdd += this.AfterItemAdd;
this.tabMenu.AfterItemRemove += this.AfterItemRemove;
}
return this.tabMenu;
}
}
/// <summary>
/// Defaults to false. True to hide tab's menu
/// </summary>
[Meta]
[ConfigOption]
[Category("4. AbstractContainer")]
[DefaultValue(false)]