FastReport

Форк
0
/
ContainerObject.cs 
392 строки · 13.3 Кб
1
using FastReport.Utils;
2
using System;
3
using System.ComponentModel;
4
using System.Drawing;
5
using System.Windows.Forms;
6

7
namespace FastReport
8
{
9
    /// <summary>
10
    /// Container object that may contain child objects.
11
    /// </summary>
12
    public partial class ContainerObject : ReportComponentBase, IParent
13
    {
14
        #region Fields
15
        private ReportComponentCollection objects;
16
        private bool updatingLayout;
17
        private string beforeLayoutEvent;
18
        private string afterLayoutEvent;
19
        private int savedOriginalObjectsCount;
20
        #endregion
21

22
        #region Properties
23
        /// <summary>
24
        /// Gets the collection of child objects.
25
        /// </summary>
26
        [Browsable(false)]
27
        public ReportComponentCollection Objects
28
        {
29
            get { return objects; }
30
        }
31

32
        /// <summary>
33
        /// This event occurs before the container layouts its child objects.
34
        /// </summary>
35
        public event EventHandler BeforeLayout;
36

37
        /// <summary>
38
        /// This event occurs after the child objects layout was finished.
39
        /// </summary>
40
        public event EventHandler AfterLayout;
41

42

43
        /// <summary>
44
        /// Gets or sets a script event name that will be fired before the container layouts its child objects.
45
        /// </summary>
46
        [Category("Build")]
47
        public string BeforeLayoutEvent
48
        {
49
            get { return beforeLayoutEvent; }
50
            set { beforeLayoutEvent = value; }
51
        }
52

53
        /// <summary>
54
        /// Gets or sets a script event name that will be fired after the child objects layout was finished.
55
        /// </summary>
56
        [Category("Build")]
57
        public string AfterLayoutEvent
58
        {
59
            get { return afterLayoutEvent; }
60
            set { afterLayoutEvent = value; }
61
        }
62

63
        #endregion
64

65
        #region IParent
66
        /// <inheritdoc/>
67
        public virtual void GetChildObjects(ObjectCollection list)
68
        {
69
            foreach (ReportComponentBase c in objects)
70
            {
71
                list.Add(c);
72
            }
73
        }
74

75
        /// <inheritdoc/>
76
        public virtual bool CanContain(Base child)
77
        {
78
            return (child is ReportComponentBase) && (child is not SubreportObject);
79
        }
80

81
        /// <inheritdoc/>
82
        public virtual void AddChild(Base child)
83
        {
84
            if (child is ReportComponentBase)
85
                objects.Add(child as ReportComponentBase);
86
        }
87

88
        /// <inheritdoc/>
89
        public virtual void RemoveChild(Base child)
90
        {
91
            if (child is ReportComponentBase)
92
                objects.Remove(child as ReportComponentBase);
93
        }
94

95
        /// <inheritdoc/>
96
        public virtual int GetChildOrder(Base child)
97
        {
98
            return objects.IndexOf(child as ReportComponentBase);
99
        }
100

101
        /// <inheritdoc/>
102
        public virtual void SetChildOrder(Base child, int order)
103
        {
104
            int oldOrder = child.ZOrder;
105
            if (oldOrder != -1 && order != -1 && oldOrder != order)
106
            {
107
                if (order > objects.Count)
108
                    order = objects.Count;
109
                if (oldOrder <= order)
110
                    order--;
111
                objects.Remove(child as ReportComponentBase);
112
                objects.Insert(order, child as ReportComponentBase);
113
            }
114
        }
115

116
        /// <inheritdoc/>
117
        public virtual void UpdateLayout(float dx, float dy)
118
        {
119
            if (updatingLayout)
120
                return;
121
            updatingLayout = true;
122
            try
123
            {
124
                RectangleF remainingBounds = new RectangleF(0, 0, Width, Height);
125
                remainingBounds.Width += dx;
126
                remainingBounds.Height += dy;
127
                foreach (ReportComponentBase c in Objects)
128
                {
129
                    if ((c.Anchor & AnchorStyles.Right) != 0)
130
                    {
131
                        if ((c.Anchor & AnchorStyles.Left) != 0)
132
                            c.Width += dx;
133
                        else
134
                            c.Left += dx;
135
                    }
136
                    else if ((c.Anchor & AnchorStyles.Left) == 0)
137
                    {
138
                        c.Left += dx / 2;
139
                    }
140
                    if ((c.Anchor & AnchorStyles.Bottom) != 0)
141
                    {
142
                        if ((c.Anchor & AnchorStyles.Top) != 0)
143
                            c.Height += dy;
144
                        else
145
                            c.Top += dy;
146
                    }
147
                    else if ((c.Anchor & AnchorStyles.Top) == 0)
148
                    {
149
                        c.Top += dy / 2;
150
                    }
151
                    switch (c.Dock)
152
                    {
153
                        case DockStyle.Left:
154
                            c.Bounds = new RectangleF(remainingBounds.Left, remainingBounds.Top, c.Width, remainingBounds.Height);
155
                            remainingBounds.X += c.Width;
156
                            remainingBounds.Width -= c.Width;
157
                            break;
158

159
                        case DockStyle.Top:
160
                            c.Bounds = new RectangleF(remainingBounds.Left, remainingBounds.Top, remainingBounds.Width, c.Height);
161
                            remainingBounds.Y += c.Height;
162
                            remainingBounds.Height -= c.Height;
163
                            break;
164

165
                        case DockStyle.Right:
166
                            c.Bounds = new RectangleF(remainingBounds.Right - c.Width, remainingBounds.Top, c.Width, remainingBounds.Height);
167
                            remainingBounds.Width -= c.Width;
168
                            break;
169

170
                        case DockStyle.Bottom:
171
                            c.Bounds = new RectangleF(remainingBounds.Left, remainingBounds.Bottom - c.Height, remainingBounds.Width, c.Height);
172
                            remainingBounds.Height -= c.Height;
173
                            break;
174

175
                        case DockStyle.Fill:
176
                            c.Bounds = remainingBounds;
177
                            remainingBounds.Width = 0;
178
                            remainingBounds.Height = 0;
179
                            break;
180
                    }
181
                }
182
            }
183
            finally
184
            {
185
                updatingLayout = false;
186
            }
187
        }
188
        #endregion
189

190
        #region Report engine
191
        /// <inheritdoc/>
192
        public override void SaveState()
193
        {
194
            base.SaveState();
195
            savedOriginalObjectsCount = Objects.Count;
196
            SetRunning(true);
197
            SetDesigning(false);
198

199
            foreach (ReportComponentBase obj in Objects)
200
            {
201
                obj.SaveState();
202
                obj.SetRunning(true);
203
                obj.SetDesigning(false);
204
                obj.OnBeforePrint(EventArgs.Empty);
205
            }
206
        }
207

208
        /// <inheritdoc/>
209
        public override void RestoreState()
210
        {
211
            base.RestoreState();
212
            while (Objects.Count > savedOriginalObjectsCount)
213
            {
214
                Objects[Objects.Count - 1].Dispose();
215
            }
216
            SetRunning(false);
217

218
            foreach (ReportComponentBase obj in Objects)
219
            {
220
                obj.OnAfterPrint(EventArgs.Empty);
221
                obj.RestoreState();
222
                obj.SetRunning(false);
223
            }
224
        }
225

226
        /// <inheritdoc/>
227
        public override void GetData()
228
        {
229
            base.GetData();
230
            var objArray = Objects.ToArray();
231
            foreach (ReportComponentBase obj in objArray)
232
            {
233
                obj.GetData();
234
                obj.OnAfterData();
235

236
                // break the component if it is of BreakableComponent an has non-empty BreakTo property
237
                if (obj is BreakableComponent && (obj as BreakableComponent).BreakTo != null &&
238
                    (obj as BreakableComponent).BreakTo.GetType() == obj.GetType())
239
                    (obj as BreakableComponent).Break((obj as BreakableComponent).BreakTo);
240
            }
241
        }
242

243
        /// <inheritdoc/>
244
        public override float CalcHeight()
245
        {
246
            OnBeforeLayout(EventArgs.Empty);
247

248
            // sort objects by Top
249
            ReportComponentCollection sortedObjects = Objects.SortByTop();
250

251
            // calc height of each object
252
            float[] heights = new float[sortedObjects.Count];
253
            for (int i = 0; i < sortedObjects.Count; i++)
254
            {
255
                ReportComponentBase obj = sortedObjects[i];
256
                float height = obj.Height;
257
                if (obj.Visible && (obj.CanGrow || obj.CanShrink))
258
                {
259
                    float height1 = obj.CalcHeight();
260
                    if ((obj.CanGrow && height1 > height) || (obj.CanShrink && height1 < height))
261
                        height = height1;
262
                }
263
                heights[i] = height;
264
            }
265

266
            // calc shift amounts
267
            float[] shifts = new float[sortedObjects.Count];
268
            for (int i = 0; i < sortedObjects.Count; i++)
269
            {
270
                ReportComponentBase parent = sortedObjects[i];
271
                float shift = heights[i] - parent.Height;
272
                if (shift == 0)
273
                    continue;
274

275
                for (int j = i + 1; j < sortedObjects.Count; j++)
276
                {
277
                    ReportComponentBase child = sortedObjects[j];
278
                    if (child.ShiftMode == ShiftMode.Never)
279
                        continue;
280

281
                    if (child.Top >= parent.Bottom - 1e-4)
282
                    {
283
                        if (child.ShiftMode == ShiftMode.WhenOverlapped &&
284
                          (child.Left > parent.Right - 1e-4 || parent.Left > child.Right - 1e-4))
285
                            continue;
286

287
                        float parentShift = shifts[i];
288
                        float childShift = shifts[j];
289
                        if (shift > 0)
290
                            childShift = Math.Max(shift + parentShift, childShift);
291
                        else
292
                            childShift = Math.Min(shift + parentShift, childShift);
293
                        shifts[j] = childShift;
294
                    }
295
                }
296
            }
297

298
            // update location and size of each component, calc max height
299
            float maxHeight = 0;
300
            for (int i = 0; i < sortedObjects.Count; i++)
301
            {
302
                ReportComponentBase obj = sortedObjects[i];
303
                DockStyle saveDock = obj.Dock;
304
                obj.Dock = DockStyle.None;
305
                obj.Height = heights[i];
306
                obj.Top += shifts[i];
307
                if (obj.Visible && obj.Bottom > maxHeight)
308
                    maxHeight = obj.Bottom;
309
                obj.Dock = saveDock;
310
            }
311

312
            // perform grow to bottom
313
            foreach (ReportComponentBase obj in Objects)
314
            {
315
                if (obj.GrowToBottom || obj.Bottom > maxHeight)
316
                    obj.Height = maxHeight - obj.Top;
317
            }
318

319
            OnAfterLayout(EventArgs.Empty);
320
            return maxHeight;
321
        }
322

323
        /// <summary>
324
        /// This method fires the <b>BeforeLayout</b> event and the script code connected to the <b>BeforeLayoutEvent</b>.
325
        /// </summary>
326
        /// <param name="e">Event data.</param>
327
        public void OnBeforeLayout(EventArgs e)
328
        {
329
            if (BeforeLayout != null)
330
                BeforeLayout(this, e);
331
            InvokeEvent(BeforeLayoutEvent, e);
332
        }
333

334
        /// <summary>
335
        /// This method fires the <b>AfterLayout</b> event and the script code connected to the <b>AfterLayoutEvent</b>.
336
        /// </summary>
337
        /// <param name="e">Event data.</param>
338
        public void OnAfterLayout(EventArgs e)
339
        {
340
            if (AfterLayout != null)
341
                AfterLayout(this, e);
342
            InvokeEvent(AfterLayoutEvent, e);
343
        }
344
        #endregion
345

346
        #region Public methods
347
        /// <inheritdoc/>
348
        public override void Assign(Base source)
349
        {
350
            base.Assign(source);
351

352
            ContainerObject src = source as ContainerObject;
353
            BeforeLayoutEvent = src.BeforeLayoutEvent;
354
            AfterLayoutEvent = src.AfterLayoutEvent;
355
        }
356

357
        /// <inheritdoc/>
358
        public override void Serialize(FRWriter writer)
359
        {
360
            ContainerObject c = writer.DiffObject as ContainerObject;
361
            base.Serialize(writer);
362

363
            if (writer.SerializeTo == SerializeTo.Preview)
364
                return;
365

366
            if (BeforeLayoutEvent != c.BeforeLayoutEvent)
367
                writer.WriteStr("BeforeLayoutEvent", BeforeLayoutEvent);
368
            if (AfterLayoutEvent != c.AfterLayoutEvent)
369
                writer.WriteStr("AfterLayoutEvent", AfterLayoutEvent);
370
        }
371

372
        /// <inheritdoc/>
373
        public override void Draw(FRPaintEventArgs e)
374
        {
375
            DrawBackground(e);
376
            DrawMarkers(e);
377
            Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
378
            base.Draw(e);
379
        }
380
        #endregion
381

382
        /// <summary>
383
        /// Initializes a new instance of the <b>ContainerObject</b> class with default settings. 
384
        /// </summary>
385
        public ContainerObject()
386
        {
387
            objects = new ReportComponentCollection(this);
388
            beforeLayoutEvent = "";
389
            afterLayoutEvent = "";
390
        }
391
    }
392
}
393

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.