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.base;
25
26 import java.io.Serializable;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import net.sf.jasperreports.engine.Deduplicable;
31 import net.sf.jasperreports.engine.JRConstants;
32 import net.sf.jasperreports.engine.JRDefaultStyleProvider;
33 import net.sf.jasperreports.engine.JRParagraph;
34 import net.sf.jasperreports.engine.JRParagraphContainer;
35 import net.sf.jasperreports.engine.JRRuntimeException;
36 import net.sf.jasperreports.engine.JRStyle;
37 import net.sf.jasperreports.engine.TabStop;
38 import net.sf.jasperreports.engine.design.events.JRChangeEventsSupport;
39 import net.sf.jasperreports.engine.design.events.JRPropertyChangeSupport;
40 import net.sf.jasperreports.engine.type.LineSpacingEnum;
41 import net.sf.jasperreports.engine.util.JRCloneUtils;
42 import net.sf.jasperreports.engine.util.ObjectUtils;
43 import net.sf.jasperreports.engine.util.StyleResolver;
44
45
46 /**
47  * @author Teodor Danciu (teodord@users.sourceforge.net)
48  */

49 public class JRBaseParagraph implements JRParagraph, Serializable, Cloneable, JRChangeEventsSupport, Deduplicable
50 {
51
52
53     /**
54      *
55      */

56     private static final long serialVersionUID = JRConstants.SERIAL_VERSION_UID;
57     
58     public static final String PROPERTY_LINE_SPACING = "lineSpacing";
59     public static final String PROPERTY_LINE_SPACING_SIZE = "lineSpacingSize";
60     public static final String PROPERTY_FIRST_LINE_INDENT = "firstLineIndent";
61     public static final String PROPERTY_LEFT_INDENT = "leftIndent";
62     public static final String PROPERTY_RIGHT_INDENT = "rightIndent";
63     public static final String PROPERTY_SPACING_BEFORE = "spacingBefore";
64     public static final String PROPERTY_SPACING_AFTER = "spacingAfter";
65     public static final String PROPERTY_TAB_STOP_WIDTH = "tabStopWidth";
66     public static final String PROPERTY_TAB_STOPS = "tabStops";
67
68
69     protected JRParagraphContainer paragraphContainer;
70
71     /**
72      *
73      */

74     protected LineSpacingEnum lineSpacing;
75     protected Float lineSpacingSize;
76     protected Integer firstLineIndent;
77     protected Integer leftIndent;
78     protected Integer rightIndent;
79     protected Integer spacingBefore;
80     protected Integer spacingAfter;
81     protected Integer tabStopWidth;
82     protected List<TabStop> tabStops;
83
84     
85     /**
86      *
87      */

88     public JRBaseParagraph(JRParagraphContainer paragraphContainer)
89     {
90         this.paragraphContainer = paragraphContainer;
91     }
92     
93     
94     @Override
95     public JRDefaultStyleProvider getDefaultStyleProvider() 
96     {
97         if (paragraphContainer != null)
98         {
99             return paragraphContainer.getDefaultStyleProvider();
100         }
101         return null;
102     }
103
104     /**
105      *
106      */

107     protected StyleResolver getStyleResolver() 
108     {
109         if (getDefaultStyleProvider() != null)
110         {
111             return getDefaultStyleProvider().getStyleResolver();
112         }
113         return StyleResolver.getInstance();
114     }
115
116     @Override
117     public JRStyle getStyle() 
118     {
119         if (paragraphContainer != null)
120         {
121             return paragraphContainer.getStyle();
122         }
123         return null;
124     }
125
126     @Override
127     public String getStyleNameReference()
128     {
129         if (paragraphContainer != null)
130         {
131             return paragraphContainer.getStyleNameReference();
132         }
133         return null;
134     }
135
136     @Override
137     public JRParagraphContainer getParagraphContainer()
138     {
139         return paragraphContainer;
140     }
141
142     @Override
143     public LineSpacingEnum getLineSpacing()
144     {
145         return getStyleResolver().getLineSpacing(this);
146     }
147
148     @Override
149     public LineSpacingEnum getOwnLineSpacing()
150     {
151         return lineSpacing;
152     }
153     
154     @Override
155     public void setLineSpacing(LineSpacingEnum lineSpacing)
156     {
157         Object old = this.lineSpacing;
158         this.lineSpacing = lineSpacing;
159         getEventSupport().firePropertyChange(PROPERTY_LINE_SPACING, old, this.lineSpacing);
160     }
161
162     @Override
163     public Float getLineSpacingSize()
164     {
165         return getStyleResolver().getLineSpacingSize(this);
166     }
167
168     @Override
169     public Float getOwnLineSpacingSize()
170     {
171         return lineSpacingSize;
172     }
173     
174     @Override
175     public void setLineSpacingSize(Float lineSpacingSize)
176     {
177         Object old = this.lineSpacingSize;
178         this.lineSpacingSize = lineSpacingSize;
179         getEventSupport().firePropertyChange(PROPERTY_LINE_SPACING_SIZE, old, this.lineSpacingSize);
180     }
181
182     @Override
183     public Integer getFirstLineIndent()
184     {
185         return getStyleResolver().getFirstLineIndent(this);
186     }
187
188     @Override
189     public Integer getOwnFirstLineIndent()
190     {
191         return firstLineIndent;
192     }
193     
194     @Override
195     public void setFirstLineIndent(Integer firstLineIndent)
196     {
197         Object old = this.firstLineIndent;
198         this.firstLineIndent = firstLineIndent;
199         getEventSupport().firePropertyChange(PROPERTY_FIRST_LINE_INDENT, old, this.firstLineIndent);
200     }
201
202     @Override
203     public Integer getLeftIndent()
204     {
205         return getStyleResolver().getLeftIndent(this);
206     }
207
208     @Override
209     public Integer getOwnLeftIndent()
210     {
211         return leftIndent;
212     }
213     
214     @Override
215     public void setLeftIndent(Integer leftIndent)
216     {
217         Object old = this.leftIndent;
218         this.leftIndent = leftIndent;
219         getEventSupport().firePropertyChange(PROPERTY_LEFT_INDENT, old, this.leftIndent);
220     }
221
222     @Override
223     public Integer getRightIndent()
224     {
225         return getStyleResolver().getRightIndent(this);
226     }
227
228     @Override
229     public Integer getOwnRightIndent()
230     {
231         return rightIndent;
232     }
233     
234     @Override
235     public void setRightIndent(Integer rightIndent)
236     {
237         Object old = this.rightIndent;
238         this.rightIndent = rightIndent;
239         getEventSupport().firePropertyChange(PROPERTY_RIGHT_INDENT, old, this.rightIndent);
240     }
241
242     @Override
243     public Integer getSpacingBefore()
244     {
245         return getStyleResolver().getSpacingBefore(this);
246     }
247
248     @Override
249     public Integer getOwnSpacingBefore()
250     {
251         return spacingBefore;
252     }
253     
254     @Override
255     public void setSpacingBefore(Integer spacingBefore)
256     {
257         Object old = this.spacingBefore;
258         this.spacingBefore = spacingBefore;
259         getEventSupport().firePropertyChange(PROPERTY_SPACING_BEFORE, old, this.spacingBefore);
260     }
261
262     @Override
263     public Integer getSpacingAfter()
264     {
265         return getStyleResolver().getSpacingAfter(this);
266     }
267
268     @Override
269     public Integer getOwnSpacingAfter()
270     {
271         return spacingAfter;
272     }
273     
274     @Override
275     public void setSpacingAfter(Integer spacingAfter)
276     {
277         Object old = this.spacingAfter;
278         this.spacingAfter = spacingAfter;
279         getEventSupport().firePropertyChange(PROPERTY_SPACING_AFTER, old, this.spacingAfter);
280     }
281
282     @Override
283     public Integer getTabStopWidth()
284     {
285         return getStyleResolver().getTabStopWidth(this);
286     }
287
288     @Override
289     public Integer getOwnTabStopWidth()
290     {
291         return tabStopWidth;
292     }
293     
294     @Override
295     public void setTabStopWidth(Integer tabStopWidth)
296     {
297         Object old = this.tabStopWidth;
298         this.tabStopWidth = tabStopWidth;
299         getEventSupport().firePropertyChange(PROPERTY_TAB_STOP_WIDTH, old, this.tabStopWidth);
300     }
301     
302     @Override
303     public TabStop[] getTabStops()
304     {
305         return getStyleResolver().getTabStops(this);
306     }
307     
308     
309     @Override
310     public TabStop[] getOwnTabStops()
311     {
312         if (tabStops == null || tabStops.size() == 0)
313         {
314             return null;
315         }
316         
317         return tabStops.toArray(new TabStop[tabStops.size()]);
318     }
319     
320     @Override
321     public void addTabStop(TabStop tabStop)
322     {
323         if (tabStops == null)
324         {
325             tabStops = new ArrayList<TabStop>();
326         }
327         
328         tabStops.add(tabStop);
329         
330         getEventSupport().fireCollectionElementAddedEvent(PROPERTY_TAB_STOPS, tabStop, tabStops.size() - 1);
331     }
332     
333     @Override
334     public void addTabStop(int index, TabStop tabStop)
335     {
336         if (tabStops == null)
337         {
338             tabStops = new ArrayList<TabStop>();
339         }
340         
341         tabStops.add(index, tabStop);
342         
343         getEventSupport().fireCollectionElementAddedEvent(PROPERTY_TAB_STOPS, tabStop, index);
344     }
345     
346     @Override
347     public void removeTabStop(TabStop tabStop)
348     {
349         if (tabStops != null)
350         {
351             int index = tabStops.indexOf(tabStop);
352             if (index >= 0)
353             {
354                 tabStops.remove(index);
355                 getEventSupport().fireCollectionElementRemovedEvent(PROPERTY_TAB_STOPS, tabStop, index);
356             }
357         }
358     }
359     
360     @Override
361     public void removeTabStop(int index)
362     {
363         if (tabStops != null)
364         {
365             if (index >= 0 && index < tabStops.size())
366             {
367                 TabStop tabStop = tabStops.remove(index);
368                 getEventSupport().fireCollectionElementRemovedEvent(PROPERTY_TAB_STOPS, tabStop, index);
369             }
370         }
371     }
372
373
374     @Override
375     public JRParagraph clone(JRParagraphContainer paragraphContainer)
376     {
377         JRBaseParagraph clone = null;
378         
379         try
380         {
381             clone = (JRBaseParagraph)super.clone();
382         }
383         catch(CloneNotSupportedException e)
384         {
385             throw new JRRuntimeException(e);
386         }
387         
388         clone.paragraphContainer = paragraphContainer;
389         clone.tabStops = JRCloneUtils.cloneList(tabStops);
390         clone.eventSupport = null;
391
392         return clone;
393     }
394     
395     private transient JRPropertyChangeSupport eventSupport;
396     
397     @Override
398     public JRPropertyChangeSupport getEventSupport()
399     {
400         synchronized (this)
401         {
402             if (eventSupport == null)
403             {
404                 eventSupport = new JRPropertyChangeSupport(this);
405             }
406         }
407         
408         return eventSupport;
409     }
410
411
412     @Override
413     public int getHashCode()
414     {
415         ObjectUtils.HashCode hash = ObjectUtils.hash();
416         hash.add(lineSpacing);
417         hash.add(lineSpacingSize);
418         hash.add(firstLineIndent);
419         hash.add(leftIndent);
420         hash.add(rightIndent);
421         hash.add(spacingBefore);
422         hash.add(spacingAfter);
423         hash.add(tabStopWidth);
424         hash.addIdentical(tabStops);
425         return hash.getHashCode();
426     }
427
428
429     @Override
430     public boolean isIdentical(Object object)
431     {
432         if (this == object)
433         {
434             return true;
435         }
436         
437         if (!(object instanceof JRBaseParagraph))
438         {
439             return false;
440         }
441         
442         JRBaseParagraph para = (JRBaseParagraph) object;
443
444         return 
445                 ObjectUtils.equals(lineSpacing, para.lineSpacing)
446                 && ObjectUtils.equals(lineSpacingSize, para.lineSpacingSize)
447                 && ObjectUtils.equals(firstLineIndent, para.firstLineIndent)
448                 && ObjectUtils.equals(leftIndent, para.leftIndent)
449                 && ObjectUtils.equals(rightIndent, para.rightIndent)
450                 && ObjectUtils.equals(spacingBefore, para.spacingBefore)
451                 && ObjectUtils.equals(spacingAfter, para.spacingAfter)
452                 && ObjectUtils.equals(tabStopWidth, para.tabStopWidth)
453                 && ObjectUtils.identical(tabStops, para.tabStops);
454     }
455
456 }
457