1 /*
2  * JasperReports - Free Java Reporting Library.
3  * Copyright (C) 2001 - 2019 TIBCO Software Inc. All rights reserved.
4  * http://www.jaspersoft.com
5  *
6  * Unless you have purchased a commercial license agreement from Jaspersoft,
7  * the following license terms apply:
8  *
9  * This program is part of JasperReports.
10  *
11  * JasperReports is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * JasperReports is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
23  */

24 package net.sf.jasperreports.engine.fill;
25
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29
30 import net.sf.jasperreports.engine.JRChild;
31 import net.sf.jasperreports.engine.JRElement;
32 import net.sf.jasperreports.engine.JRElementGroup;
33 import net.sf.jasperreports.engine.JRVisitor;
34 import net.sf.jasperreports.engine.util.ElementsVisitorUtils;
35
36
37 /**
38  * @author Teodor Danciu (teodord@users.sourceforge.net)
39  */

40 public class JRFillElementGroup implements JRElementGroup, JRFillCloneable
41 {
42
43
44     /**
45      *
46      */

47     protected List<JRChild> children = new ArrayList<JRChild>();
48     protected JRElementGroup elementGroup;
49
50     /**
51      *
52      */

53     protected JRFillElement[] elements;
54
55     /**
56      *
57      */

58     protected JRElement topElementInGroup;
59     protected JRElement bottomElementInGroup;
60     private Integer stretchHeightDiff;
61
62
63     /**
64      *
65      */

66     protected JRFillElementGroup(
67         JRElementGroup elementGrp, 
68         JRFillObjectFactory factory
69         )
70     {
71         if (elementGrp != null)
72         {
73             factory.put(elementGrp, this);
74
75             /*   */
76             List<JRChild> list = elementGrp.getChildren();
77             if (list != null && list.size() > 0)
78             {
79                 for(int i = 0; i < list.size(); i++)
80                 {
81                     JRChild child = list.get(i);
82                     child = (JRChild)factory.getVisitResult(child);
83                     children.add(child);
84                 }
85             }
86     
87             /*   */
88             getElements();
89     
90             elementGroup = (JRElementGroup)factory.getVisitResult(elementGrp.getElementGroup());
91         }
92     }
93
94     
95     protected JRFillElementGroup(JRFillElementGroup elementGrp, JRFillCloneFactory factory)
96     {
97         factory.put(elementGrp, this);
98
99         List<JRChild> list = elementGrp.getChildren();
100         if (list != null)
101         {
102             for (int i = 0; i < list.size(); i++)
103             {
104                 JRFillCloneable child = (JRFillCloneable) list.get(i);
105                 JRFillCloneable clone = child.createClone(factory);
106                 children.add((JRChild)clone);
107             }
108         }
109
110         getElements();
111
112         elementGroup = (JRFillElementGroup) factory.getClone((JRFillElementGroup) elementGrp.getElementGroup());
113     }
114
115
116     @Override
117     public List<JRChild> getChildren()
118     {
119         return this.children;
120     }
121
122
123     @Override
124     public JRElementGroup getElementGroup()
125     {
126         return this.elementGroup;
127     }
128
129
130     @Override
131     public JRElement[] getElements()
132     {
133         if (this.elements == null)
134         {
135             if (this.children != null)
136             {
137                 List<JRElement> allElements = new ArrayList<JRElement>();
138                 Object child = null;
139                 JRElement[] childElementArray = null;
140                 for(int i = 0; i < this.children.size(); i++)
141                 {
142                     child = this.children.get(i);
143                     if (child instanceof JRFillElement)
144                     {
145                         allElements.add((JRElement)child);
146                     }
147                     else if (child instanceof JRFillElementGroup)
148                     {
149                         childElementArray = ((JRFillElementGroup)child).getElements();
150                         if (childElementArray != null)
151                         {
152                             allElements.addAll( Arrays.asList(childElementArray) );
153                         }
154                     }
155                 }
156                 
157                 this.elements = new JRFillElement[allElements.size()];
158                 allElements.toArray(this.elements);
159             }
160         }
161         
162         return this.elements;
163     }
164
165
166     @Override
167     public JRElement getElementByKey(String key)
168     {
169         return null;
170     }
171
172
173     /**
174      *
175      */

176     protected void reset()
177     {
178         stretchHeightDiff = null;
179     }
180
181
182     /**
183      *
184      */

185     protected int getStretchHeightDiff()
186     {
187         if (stretchHeightDiff == null)
188         {
189             stretchHeightDiff = 0;
190             
191             setTopBottomElements();
192
193             JRElement[] allElements = getElements();
194
195             if (allElements != null && allElements.length > 0)
196             {
197                 JRFillElement topElem = null;
198                 JRFillElement bottomElem = null;
199
200                 for(int i = 0; i < allElements.length; i++)
201                 {
202                     JRFillElement element = (JRFillElement)allElements[i];
203                     //if (element != this && element.isToPrint())
204                     if (element.isToPrint())
205                     {
206                         if (
207                             topElem == null ||
208                             (
209                             element.getRelativeY() + element.getStretchHeight() <
210                             topElem.getRelativeY() + topElem.getStretchHeight())
211                             )
212                         {
213                             topElem = element;
214                         }
215
216                         if (
217                             bottomElem == null ||
218                             (
219                             element.getRelativeY() + element.getStretchHeight() >
220                             bottomElem.getRelativeY() + bottomElem.getStretchHeight())
221                             )
222                         {
223                             bottomElem = element;
224                         }
225                     }
226                 }
227
228                 if (topElem != null)
229                 {
230                     stretchHeightDiff = 
231                         bottomElem.getRelativeY() + bottomElem.getStretchHeight() - topElem.getRelativeY() -
232                         (bottomElementInGroup.getY() + bottomElementInGroup.getHeight() - topElementInGroup.getY());
233                 }
234
235                 if (stretchHeightDiff < 0)
236                 {
237                     stretchHeightDiff = 0;
238                 }
239             }
240         }
241         
242         return stretchHeightDiff;
243     }
244
245
246     /**
247      *
248      */

249     private void setTopBottomElements()
250     {
251         if (topElementInGroup == null// some element groups such as JRFillElementContainer already set this during their initElements
252         {
253             JRElement[] allElements = getElements();
254             
255             if (allElements != null && allElements.length > 0)
256             {
257                 for (JRElement element : allElements)
258                 {
259                     if (
260                         topElementInGroup == null ||
261                         (
262                         element.getY() + element.getHeight() <
263                         topElementInGroup.getY() + topElementInGroup.getHeight())
264                         )
265                     {
266                         topElementInGroup = element;
267                     }
268
269                     if (
270                         bottomElementInGroup == null ||
271                         (
272                         element.getY() + element.getHeight() >
273                         bottomElementInGroup.getY() + bottomElementInGroup.getHeight())
274                         )
275                     {
276                         bottomElementInGroup = element;
277                     }
278                 }
279             }
280         }
281     }
282
283
284     @Override
285     public void visit(JRVisitor visitor)
286     {
287         visitor.visitElementGroup(this);
288         
289         if (ElementsVisitorUtils.visitDeepElements(visitor))
290         {
291             ElementsVisitorUtils.visitElements(visitor, children);
292         }
293     }
294
295     
296     @Override
297     public JRFillCloneable createClone(JRFillCloneFactory factory)
298     {
299         return new JRFillElementGroup(this, factory);
300     }
301
302     @Override
303     public Object clone() 
304     {
305         throw new UnsupportedOperationException();
306     }
307
308     @Override
309     public Object clone(JRElementGroup parentGroup) 
310     {
311         throw new UnsupportedOperationException();
312     }
313 }
314