View Javadoc
1   /**
2    * This file Copyright (c) 2010-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.templating.editor.client.widget.placeholder;
35  
36  
37  import static info.magnolia.templating.editor.client.jsni.JavascriptUtils.getI18nMessage;
38  
39  import info.magnolia.rendering.template.AreaDefinition;
40  import info.magnolia.templating.editor.client.PageEditor;
41  import info.magnolia.templating.editor.client.dom.CMSComment;
42  import info.magnolia.templating.editor.client.dom.MgnlElement;
43  import info.magnolia.templating.elements.AreaElement;
44  
45  import java.util.Map;
46  
47  import com.google.gwt.dom.client.Element;
48  import com.google.gwt.dom.client.NativeEvent;
49  import com.google.gwt.dom.client.Node;
50  import com.google.gwt.dom.client.Style.Cursor;
51  import com.google.gwt.event.dom.client.ClickEvent;
52  import com.google.gwt.event.dom.client.ClickHandler;
53  import com.google.gwt.event.dom.client.MouseDownEvent;
54  import com.google.gwt.event.dom.client.MouseDownHandler;
55  import com.google.gwt.user.client.ui.FlowPanel;
56  import com.google.gwt.user.client.ui.Label;
57  import com.google.gwt.user.client.ui.PushButton;
58  
59  /**
60   * A Widget for adding components to area.
61   */
62  public class ComponentPlaceHolder extends AbstractPlaceHolder {
63  
64      private boolean showAddButton = false;
65      private boolean showAddComponentArea = false;
66      private String availableComponents = "";
67      private String type = "";
68      private String areaWorkspace = "";
69      private String areaPath = "";
70      private final FlowPanel buttonWrapper;
71      private String label;
72      private String labelString;
73  
74  
75      public ComponentPlaceHolder(MgnlElement mgnlElement) throws IllegalArgumentException {
76  
77          super(mgnlElement);
78  
79          checkMandatories(mgnlElement.getAttributes());
80  
81          this.addStyleName("component");
82  
83          FlowPanel controlBar = new FlowPanel();
84          controlBar.setStyleName("mgnlEditorBar");
85          controlBar.addStyleName("placeholder");
86  
87          buttonWrapper = new FlowPanel();
88          buttonWrapper.setStylePrimaryName("mgnlEditorBarButtons");
89  
90          controlBar.add(buttonWrapper);
91  
92          // if the add new component area should be visible
93          if (this.showAddComponentArea && !this.showAddButton) { // maximum of components is reached - show add new component area with the maximum reached message, but without the ADD button
94              labelString = getI18nMessage("buttons.component.maximum.js");
95          } else { // maximum of components is NOT reached - show add new component area with ADD button
96              labelString = getI18nMessage("buttons.component.new.js");
97              if (this.label != null && !this.label.isEmpty()) {
98                  labelString = getI18nMessage("buttons.new.js") + " " + label + " " + getI18nMessage("buttons.component.js");
99              }
100         }
101 
102 
103         Label labelName = new Label(labelString);
104         labelName.setStyleName("mgnlEditorBarLabel");
105         controlBar.add(labelName);
106 
107         add(controlBar);
108 
109         Element marker = getMgnlElement().getComponentElement();
110         boolean onlyBar = (marker != null && marker.getAttribute(AreaDefinition.CMS_ADD).equals("bar")) ? true: false;
111 
112         if (!onlyBar) {
113             createBoxPlaceHolder();
114         }
115 
116         setVisible(false);
117         createButtons();
118         attach();
119     }
120 
121     private void createBoxPlaceHolder() {
122 
123         FlowPanel elementWrapper = new FlowPanel();
124         elementWrapper.setStyleName("mgnlEditorPlaceholderElements");
125 
126         if (this.showAddButton) {
127             elementWrapper.getElement().getStyle().setCursor(Cursor.POINTER);
128             elementWrapper.addDomHandler(new MouseDownHandler() {
129 
130                 @Override
131                 public void onMouseDown(MouseDownEvent event) {
132                     if(event.getNativeButton() == NativeEvent.BUTTON_RIGHT)  {
133                         return;
134                     }
135                     PageEditor.addComponent(areaWorkspace, areaPath, null, availableComponents);
136                 }
137             }, MouseDownEvent.getType());
138         }
139         add(elementWrapper);
140 
141     }
142 
143     private void createButtons() {
144 
145         if (this.showAddButton) {
146             PushButton button = new PushButton();
147             button.setTitle(getI18nMessage("buttons.add.js") + " " + labelString);
148             button.setStylePrimaryName("mgnlEditorPushButton");
149             button.addStyleName("add");
150 
151             button.addClickHandler(new ClickHandler() {
152                 @Override
153                 public void onClick(ClickEvent event) {
154                     PageEditor.addComponent(areaWorkspace, areaPath, null, availableComponents);
155                 }
156             });
157             buttonWrapper.add(button);
158         }
159     }
160 
161     public void attach() {
162         Element parent = getMgnlElement().getComponentElement();
163 
164         if (parent == null) {
165             if (getMgnlElement().getLastElement() != null && getMgnlElement().getFirstElement() == getMgnlElement().getLastElement()) {
166                 attach(getMgnlElement());
167             }
168             else {
169                 CMSComment endCmsComment = getMgnlElement().getEndComment();
170                 if (endCmsComment == null) {
171                     throw new IllegalStateException("Cannot attach placeholder for '" + this.areaPath +
172                             "'. It's possible that the template script for this area or for some subcomponent is incorrect. Please check that all HTML tags are closed properly.");
173                 } else {
174                     attach(endCmsComment.getElement());
175                 }
176             }
177         }
178         else {
179             parent.insertFirst(getElement());
180         }
181         onAttach();
182         PageEditor.model.addComponentPlaceHolder(getMgnlElement(), this);
183     }
184 
185     public void attach(MgnlElement mgnlElement) {
186         Element element = mgnlElement.getFirstElement();
187         if (element != null) {
188             element.appendChild(getElement());
189         }
190     }
191 
192     public void attach(Element element) {
193         final Node parentNode = element.getParentNode();
194         parentNode.insertBefore(getElement(), element);
195     }
196 
197     private void checkMandatories(Map<String, String> attributes) throws IllegalArgumentException {
198 
199         this.showAddButton = Boolean.parseBoolean(attributes.get(AreaElement.SHOW_ADD_BUTTON));
200         this.showAddComponentArea = Boolean.parseBoolean(attributes.get(AreaElement.SHOW_NEW_COMPONENT_AREA));
201         this.type = attributes.get("type");
202 
203         String areaContent = attributes.get("content");
204         int i = areaContent.indexOf(':');
205         this.areaWorkspace = areaContent.substring(0, i);
206         this.areaPath = areaContent.substring(i + 1);
207 
208         this.label = getMgnlElement().getAttribute("label");
209 
210         if(AreaDefinition.TYPE_NO_COMPONENT.equals(this.type)) {
211             this.availableComponents = "";
212         }
213         else {
214             this.availableComponents = attributes.get("availableComponents");
215         }
216 
217         if (availableComponents.equals("")) {
218             throw new IllegalArgumentException();
219         }
220 
221         if (this.type.equals(AreaDefinition.TYPE_SINGLE) && !getMgnlElement().getComponents().isEmpty()) {
222             throw new IllegalArgumentException();
223         }
224 
225     }
226 
227 }