View Javadoc
1   /*
2    * Copyright (c) 2011-2024 PrimeFaces Extensions
3    *
4    *  Permission is hereby granted, free of charge, to any person obtaining a copy
5    *  of this software and associated documentation files (the "Software"), to deal
6    *  in the Software without restriction, including without limitation the rights
7    *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    *  copies of the Software, and to permit persons to whom the Software is
9    *  furnished to do so, subject to the following conditions:
10   *
11   *  The above copyright notice and this permission notice shall be included in
12   *  all copies or substantial portions of the Software.
13   *
14   *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20   *  THE SOFTWARE.
21   */
22  package org.primefaces.extensions.component.layout;
23  
24  import javax.faces.FacesException;
25  import javax.faces.component.UIComponent;
26  import javax.faces.component.UIComponentBase;
27  import javax.faces.component.UIForm;
28  import javax.faces.component.html.HtmlPanelGroup;
29  import javax.faces.context.FacesContext;
30  import javax.faces.event.ComponentSystemEvent;
31  import javax.faces.event.ListenerFor;
32  import javax.faces.event.PreRenderComponentEvent;
33  
34  import org.primefaces.component.outputpanel.OutputPanel;
35  import org.primefaces.extensions.model.layout.LayoutOptions;
36  
37  /**
38   * <code>LayoutPane</code> component.
39   *
40   * @author Oleg Varaksin / last modified by Melloware
41   * @since 0.2
42   */
43  @ListenerFor(systemEventClass = PreRenderComponentEvent.class)
44  public class LayoutPane extends UIComponentBase {
45  
46      public static final String COMPONENT_TYPE = "org.primefaces.extensions.component.LayoutPane";
47      public static final String COMPONENT_FAMILY = "org.primefaces.extensions.component";
48      private static final String DEFAULT_RENDERER = "org.primefaces.extensions.component.LayoutPaneRenderer";
49  
50      private LayoutOptions options;
51  
52      /**
53       * Properties that are tracked by state saving.
54       *
55       * @author Oleg Varaksin / last modified by $Author$
56       * @version $Revision$
57       */
58      @SuppressWarnings("java:S115")
59      protected enum PropertyKeys {
60  
61          // @formatter:off
62          position,
63          paneSelector,
64          combinedPosition,
65          styleHeader,
66          styleClassHeader,
67          styleContent,
68          styleClassContent,
69          resizable,
70          slideable,
71          closable,
72          size,
73          minSize,
74          maxSize,
75          minWidth,
76          maxWidth,
77          minHeight,
78          maxHeight,
79          spacing_open,
80          spacing_closed,
81          initClosed,
82          initHidden,
83          resizeWhileDragging,
84          togglerTip_open("Open"),
85          togglerTip_closed("Close"),
86          resizerTip("Resize"),
87          sliderTip("Slide"),
88          maskContents,
89          maskObjects;
90          // @formatter:on
91  
92          private final String toString;
93  
94          PropertyKeys(String toString) {
95              this.toString = toString;
96          }
97  
98          PropertyKeys() {
99              toString = null;
100         }
101 
102         @Override
103         public String toString() {
104             return ((toString != null) ? toString : super.toString());
105         }
106     }
107 
108     public LayoutPane() {
109         setRendererType(DEFAULT_RENDERER);
110     }
111 
112     @Override
113     public String getFamily() {
114         return COMPONENT_FAMILY;
115     }
116 
117     public String getStyleHeader() {
118         return (String) getStateHelper().eval(PropertyKeys.styleHeader, null);
119     }
120 
121     public void setStyleHeader(final String styleHeader) {
122         getStateHelper().put(PropertyKeys.styleHeader, styleHeader);
123     }
124 
125     public String getStyleClassHeader() {
126         return (String) getStateHelper().eval(PropertyKeys.styleClassHeader, null);
127     }
128 
129     public void setStyleClassHeader(final String styleClassHeader) {
130         getStateHelper().put(PropertyKeys.styleClassHeader, styleClassHeader);
131     }
132 
133     public String getStyleContent() {
134         return (String) getStateHelper().eval(PropertyKeys.styleContent, null);
135     }
136 
137     public void setStyleContent(final String styleContent) {
138         getStateHelper().put(PropertyKeys.styleContent, styleContent);
139     }
140 
141     public String getStyleClassContent() {
142         return (String) getStateHelper().eval(PropertyKeys.styleClassContent, null);
143     }
144 
145     public void setStyleClassContent(final String styleClassContent) {
146         getStateHelper().put(PropertyKeys.styleClassContent, styleClassContent);
147     }
148 
149     // position "north" | "south" | "west" | "east" | "center"
150     public String getPosition() {
151         return (String) getStateHelper().eval(PropertyKeys.position, Layout.PANE_POSITION_CENTER);
152     }
153 
154     public void setPosition(final String position) {
155         getStateHelper().put(PropertyKeys.position, position);
156     }
157 
158     public String getPaneSelector() {
159         return (String) getStateHelper().eval(PropertyKeys.paneSelector, null);
160     }
161 
162     public void setPaneSelector(final String paneSelector) {
163         getStateHelper().put(PropertyKeys.paneSelector, paneSelector);
164     }
165 
166     public String getCombinedPosition() {
167         return (String) getStateHelper().eval(PropertyKeys.combinedPosition, Layout.PANE_POSITION_CENTER);
168     }
169 
170     public void setCombinedPosition(final String combinedPosition) {
171         getStateHelper().put(PropertyKeys.combinedPosition, combinedPosition);
172     }
173 
174     public String getTogglerTipOpen() {
175         return (String) getStateHelper().eval(PropertyKeys.togglerTip_open, null);
176     }
177 
178     public void setTogglerTipOpen(final String togglerTipOpen) {
179         getStateHelper().put(PropertyKeys.togglerTip_open, togglerTipOpen);
180     }
181 
182     public String getTogglerTipClosed() {
183         return (String) getStateHelper().eval(PropertyKeys.togglerTip_closed, null);
184     }
185 
186     public void setTogglerTipClosed(final String togglerTipClosed) {
187         getStateHelper().put(PropertyKeys.togglerTip_closed, togglerTipClosed);
188     }
189 
190     public String getResizerTip() {
191         return (String) getStateHelper().eval(PropertyKeys.resizerTip, null);
192     }
193 
194     public void setResizerTip(final String resizerTip) {
195         getStateHelper().put(PropertyKeys.resizerTip, resizerTip);
196     }
197 
198     public String getSliderTip() {
199         return (String) getStateHelper().eval(PropertyKeys.sliderTip, null);
200     }
201 
202     public void setSliderTip(final String sliderTip) {
203         getStateHelper().put(PropertyKeys.sliderTip, sliderTip);
204     }
205 
206     public boolean isResizable() {
207         return (Boolean) getStateHelper().eval(PropertyKeys.resizable, true);
208     }
209 
210     public void setResizable(final boolean resizable) {
211         getStateHelper().put(PropertyKeys.resizable, resizable);
212     }
213 
214     public boolean isSlidable() {
215         return (Boolean) getStateHelper().eval(PropertyKeys.slideable, true);
216     }
217 
218     public void setSlidable(final boolean slideable) {
219         getStateHelper().put(PropertyKeys.slideable, slideable);
220     }
221 
222     public boolean isClosable() {
223         return (Boolean) getStateHelper().eval(PropertyKeys.closable, true);
224     }
225 
226     public void setClosable(final boolean closable) {
227         getStateHelper().put(PropertyKeys.closable, closable);
228     }
229 
230     public String getSize() {
231         return (String) getStateHelper().eval(PropertyKeys.size, null);
232     }
233 
234     public void setSize(final String size) {
235         getStateHelper().put(PropertyKeys.size, size);
236     }
237 
238     public String getMinSize() {
239         return (String) getStateHelper().eval(PropertyKeys.minSize, null);
240     }
241 
242     public void setMinSize(final String minSize) {
243         getStateHelper().put(PropertyKeys.minSize, minSize);
244     }
245 
246     public String getMaxSize() {
247         return (String) getStateHelper().eval(PropertyKeys.maxSize, null);
248     }
249 
250     public void setMaxSize(final String maxSize) {
251         getStateHelper().put(PropertyKeys.maxSize, maxSize);
252     }
253 
254     public String getMinWidth() {
255         return (String) getStateHelper().eval(PropertyKeys.minWidth, null);
256     }
257 
258     public void setMinWidth(final String minWidth) {
259         getStateHelper().put(PropertyKeys.minWidth, minWidth);
260     }
261 
262     public String getMaxWidth() {
263         return (String) getStateHelper().eval(PropertyKeys.maxWidth, null);
264     }
265 
266     public void setMaxWidth(final String maxWidth) {
267         getStateHelper().put(PropertyKeys.maxWidth, maxWidth);
268     }
269 
270     public String getMinHeight() {
271         return (String) getStateHelper().eval(PropertyKeys.minHeight, null);
272     }
273 
274     public void setMinHeight(final String minHeight) {
275         getStateHelper().put(PropertyKeys.minHeight, minHeight);
276     }
277 
278     public String getMaxHeight() {
279         return (String) getStateHelper().eval(PropertyKeys.maxHeight, null);
280     }
281 
282     public void setMaxHeight(final String maxHeight) {
283         getStateHelper().put(PropertyKeys.maxHeight, maxHeight);
284     }
285 
286     public int getSpacingOpen() {
287         return (Integer) getStateHelper().eval(PropertyKeys.spacing_open, 6);
288     }
289 
290     public void setSpacingOpen(final int spacingOpen) {
291         getStateHelper().put(PropertyKeys.spacing_open, spacingOpen);
292     }
293 
294     public int getSpacingClosed() {
295         return (Integer) getStateHelper().eval(PropertyKeys.spacing_closed, 6);
296     }
297 
298     public void setSpacingClosed(final int spacingClosed) {
299         getStateHelper().put(PropertyKeys.spacing_closed, spacingClosed);
300     }
301 
302     public boolean isInitClosed() {
303         return (Boolean) getStateHelper().eval(PropertyKeys.initClosed, false);
304     }
305 
306     public void setInitClosed(final boolean initClosed) {
307         getStateHelper().put(PropertyKeys.initClosed, initClosed);
308     }
309 
310     public boolean isInitHidden() {
311         return (Boolean) getStateHelper().eval(PropertyKeys.initHidden, false);
312     }
313 
314     public void setInitHidden(final boolean initHidden) {
315         getStateHelper().put(PropertyKeys.initHidden, initHidden);
316     }
317 
318     public boolean isResizeWhileDragging() {
319         return (Boolean) getStateHelper().eval(PropertyKeys.resizeWhileDragging, false);
320     }
321 
322     public void setResizeWhileDragging(final boolean resizeWhileDragging) {
323         getStateHelper().put(PropertyKeys.resizeWhileDragging, resizeWhileDragging);
324     }
325 
326     public boolean isMaskContents() {
327         return (Boolean) getStateHelper().eval(PropertyKeys.maskContents, false);
328     }
329 
330     public void setMaskContents(final boolean maskContents) {
331         getStateHelper().put(PropertyKeys.maskContents, maskContents);
332     }
333 
334     public boolean isMaskObjects() {
335         return (Boolean) getStateHelper().eval(PropertyKeys.maskObjects, false);
336     }
337 
338     public void setMaskObjects(final boolean maskObjects) {
339         getStateHelper().put(PropertyKeys.maskObjects, maskObjects);
340     }
341 
342     @Override
343     public void processEvent(final ComponentSystemEvent event) {
344         super.processEvent(event);
345 
346         if (!(event instanceof PreRenderComponentEvent) || !getLayout().isBuildOptions()) {
347             return;
348         }
349 
350         setOptions(getParent());
351     }
352 
353     public LayoutOptions getOptions() {
354         if (options != null) {
355             return options;
356         }
357 
358         // create options object
359         options = new LayoutOptions();
360 
361         final boolean isResizable = isResizable();
362         if (!isResizable) {
363             options.addOption(PropertyKeys.resizable.toString(), false);
364         }
365 
366         final boolean isSlidable = isSlidable();
367         if (!isSlidable) {
368             options.addOption(PropertyKeys.slideable.toString(), false);
369         }
370 
371         final boolean isClosable = isClosable();
372         if (!isClosable) {
373             options.addOption(PropertyKeys.closable.toString(), false);
374         }
375 
376         options.addOption(PropertyKeys.spacing_open.toString(), getSpacingOpen());
377         options.addOption(PropertyKeys.spacing_closed.toString(), getSpacingClosed());
378 
379         final boolean initClosed = isInitClosed();
380         if (initClosed) {
381             options.addOption(PropertyKeys.initClosed.toString(), true);
382         }
383 
384         final boolean initHidden = isInitHidden();
385         if (initHidden) {
386             options.addOption(PropertyKeys.initHidden.toString(), true);
387         }
388 
389         final boolean isResizeWhileDragging = isResizeWhileDragging();
390         if (isResizeWhileDragging) {
391             options.addOption(PropertyKeys.resizeWhileDragging.toString(), true);
392         }
393 
394         final boolean isMaskContents = isMaskContents();
395         if (isMaskContents) {
396             options.addOption(PropertyKeys.maskContents.toString(), true);
397             options.addOption("contentIgnoreSelector", ".ui-layout-mask");
398         }
399 
400         final boolean isMaskObjects = isMaskObjects();
401         if (isMaskObjects) {
402             options.addOption(PropertyKeys.maskObjects.toString(), true);
403             if (!isMaskContents) {
404                 options.addOption("contentIgnoreSelector", ".ui-layout-mask");
405             }
406         }
407 
408         final String paneSelector = getPaneSelector();
409         if (paneSelector != null) {
410             options.addOption(PropertyKeys.paneSelector.toString(), paneSelector);
411         }
412 
413         final String size = getSize();
414         if (size != null) {
415             options.addOption(PropertyKeys.size.toString(), size);
416         }
417 
418         final String minSize = getMinSize();
419         if (minSize != null) {
420             options.addOption(PropertyKeys.minSize.toString(), minSize);
421         }
422 
423         final String maxSize = getMaxSize();
424         if (maxSize != null) {
425             options.addOption(PropertyKeys.maxSize.toString(), maxSize);
426         }
427 
428         final String minWidth = getMinWidth();
429         if (minWidth != null) {
430             options.addOption(PropertyKeys.minWidth.toString(), minWidth);
431         }
432 
433         final String maxWidth = getMaxWidth();
434         if (maxWidth != null) {
435             options.addOption(PropertyKeys.maxWidth.toString(), maxWidth);
436         }
437 
438         final String minHeight = getMinHeight();
439         if (minHeight != null) {
440             options.addOption(PropertyKeys.minHeight.toString(), minHeight);
441         }
442 
443         final String maxHeight = getMaxHeight();
444         if (maxHeight != null) {
445             options.addOption(PropertyKeys.maxHeight.toString(), maxHeight);
446         }
447 
448         final LayoutOptions tips = new LayoutOptions();
449         options.setTips(tips);
450 
451         final String resizerTip = getResizerTip();
452         if (resizerTip != null) {
453             tips.addOption(PropertyKeys.resizerTip.toString(), resizerTip);
454         }
455 
456         final String sliderTip = getSliderTip();
457         if (sliderTip != null) {
458             tips.addOption(PropertyKeys.sliderTip.toString(), sliderTip);
459         }
460 
461         final String togglerTipOpen = getTogglerTipOpen();
462         if (togglerTipOpen != null) {
463             tips.addOption(PropertyKeys.togglerTip_open.toString(), togglerTipOpen);
464         }
465 
466         final String togglerTipClosed = getTogglerTipClosed();
467         if (togglerTipClosed != null) {
468             tips.addOption(PropertyKeys.togglerTip_closed.toString(), togglerTipClosed);
469         }
470 
471         return options;
472     }
473 
474     private void setOptions(final UIComponent parent) {
475         // create layout options for this pane via attributes defined in
476         // pe:layoutPane
477         final String position = getPosition();
478         final LayoutOptions thisLayoutOptions = getOptions();
479         LayoutOptions parentOpts;
480 
481         if (parent instanceof LayoutPane) {
482             final LayoutOptions parentLayoutOptions = ((LayoutPane) parent).getOptions();
483             parentOpts = parentLayoutOptions.getChildOptions();
484             if (parentOpts == null) {
485                 parentOpts = new LayoutOptions();
486                 parentLayoutOptions.setChildOptions(parentOpts);
487             }
488         }
489         else if (parent instanceof Layout) {
490             parentOpts = (LayoutOptions) ((Layout) parent).getOptions();
491             if (parentOpts == null) {
492                 final Layout layout = (Layout) parent;
493                 parentOpts = new LayoutOptions();
494                 layout.setOptions(parentOpts);
495 
496                 // options for all panes
497                 final LayoutOptions defaults = new LayoutOptions();
498                 parentOpts.setPanesOptions(defaults);
499                 final LayoutOptions tips = new LayoutOptions();
500                 defaults.setTips(tips);
501 
502                 final String resizerTip = layout.getResizerTip();
503                 if (resizerTip != null) {
504                     tips.addOption(Layout.PropertyKeys.resizerTip.toString(), resizerTip);
505                 }
506 
507                 final String sliderTip = layout.getSliderTip();
508                 if (sliderTip != null) {
509                     tips.addOption(Layout.PropertyKeys.sliderTip.toString(), sliderTip);
510                 }
511 
512                 final String togglerTipOpen = layout.getTogglerTipOpen();
513                 if (togglerTipOpen != null) {
514                     tips.addOption(Layout.PropertyKeys.togglerTip_open.toString(), togglerTipOpen);
515                 }
516 
517                 final String togglerTipClosed = layout.getTogglerTipClosed();
518                 if (togglerTipClosed != null) {
519                     tips.addOption(Layout.PropertyKeys.togglerTip_closed.toString(), togglerTipClosed);
520                 }
521 
522                 final boolean maskPanesEarly = layout.isMaskPanesEarly();
523                 if (maskPanesEarly) {
524                     parentOpts.addOption(Layout.PropertyKeys.maskPanesEarly.toString(), true);
525                 }
526             }
527         }
528         else if ((parent instanceof UIForm) || (parent instanceof HtmlPanelGroup
529                     && Layout.STYLE_CLASS_LAYOUT_CONTENT.equals(((HtmlPanelGroup) parent).getStyleClass())
530                     && "block".equals(((HtmlPanelGroup) parent).getLayout()))
531                     || (parent instanceof OutputPanel
532                                 && Layout.STYLE_CLASS_LAYOUT_CONTENT.equals(((OutputPanel) parent).getStyleClass()))
533                     ||
534                     (parent != null && parent.toString().contains(Layout.STYLE_CLASS_LAYOUT_CONTENT))) {
535             setOptions(parent.getParent());
536 
537             return;
538         }
539         else {
540             throw new FacesException(
541                         "LayoutPane can be only placed within another LayoutPane, Layout, UIForm or DIV with class 'ui-layout-content'");
542         }
543 
544         if (Layout.PANE_POSITION_CENTER.equals(position)) {
545             parentOpts.setCenterOptions(thisLayoutOptions);
546         }
547         else if (Layout.PANE_POSITION_NORTH.equals(position)) {
548             parentOpts.setNorthOptions(thisLayoutOptions);
549         }
550         else if (Layout.PANE_POSITION_SOUTH.equals(position)) {
551             parentOpts.setSouthOptions(thisLayoutOptions);
552         }
553         else if (Layout.PANE_POSITION_WEST.equals(position)) {
554             parentOpts.setWestOptions(thisLayoutOptions);
555         }
556         else if (Layout.PANE_POSITION_EAST.equals(position)) {
557             parentOpts.setEastOptions(thisLayoutOptions);
558         }
559         else {
560             throw new FacesException("Pane position " + position
561                         + " is invalid. Valid positions are 'center', 'north' 'south', 'west', 'east'");
562         }
563     }
564 
565     private Layout getLayout() {
566         UIComponent parent = getParent();
567 
568         while (!(parent instanceof Layout)) {
569             parent = parent.getParent();
570         }
571 
572         return (Layout) parent;
573     }
574 
575     @Override
576     public Object saveState(FacesContext context) {
577         // reset component for MyFaces view pooling
578         options = null;
579 
580         return super.saveState(context);
581     }
582 }