View Javadoc
1   /**
2    * This file Copyright (c) 2018 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.ui.incub;
35  
36  import java.util.Optional;
37  
38  import org.apache.commons.lang3.StringUtils;
39  
40  import com.vaadin.ui.Button;
41  import com.vaadin.ui.Component;
42  import com.vaadin.ui.CustomField;
43  import com.vaadin.ui.HorizontalLayout;
44  import com.vaadin.ui.NativeButton;
45  import com.vaadin.ui.TextField;
46  import com.vaadin.ui.VerticalLayout;
47  
48  /**
49   * A base custom field comprising a text field and a button placed to its immediate right.
50   * A {@link PropertyTranslator} can be set in order to have a different display and property stored.
51   * For example, display can be the Item path and value stored is the identifier of the Item.
52   *
53   * TODO compare with actual V8 impl in new UI framework and/or drop.
54   */
55  public class LinkField extends CustomField<String> {
56      // Define layout and component
57      private final VerticalLayout rootLayout = new VerticalLayout();
58      private final HorizontalLayout linkLayout = new HorizontalLayout();
59      private final TextField textField = new TextField();
60      private final Button selectButton = new NativeButton();
61      private Component contentPreview;
62      private String buttonCaptionNew;
63      private String buttonCaptionOther;
64      private boolean isFieldEditable;
65  
66      public LinkField() {
67      }
68  
69      @Override
70      protected Component initContent() {
71          addStyleName("linkfield");
72          // Initialize root
73          rootLayout.setSizeFull();
74          rootLayout.setMargin(false);
75          rootLayout.setSpacing(true);
76          // Handle Text Field
77          textField.setWidth(100, Unit.PERCENTAGE);
78          textField.addValueChangeListener(event ->
79                  setValue(String.valueOf(Optional.ofNullable(event.getValue()).orElse(""))));
80  
81          // Handle Link Layout (Text Field & Select Button)
82          linkLayout.setSizeFull();
83          linkLayout.setSpacing(false);
84          linkLayout.addComponents(textField);
85          linkLayout.setExpandRatio(textField, 1);
86          //linkLayout.setComponentAlignment(textField, Alignment.MIDDLE_LEFT);
87          // Only Handle Select button if the Text field is not Read Only.
88          if (!textField.isReadOnly()) {
89              selectButton.addStyleName("magnoliabutton");
90              linkLayout.addComponent(selectButton);
91              linkLayout.setExpandRatio(selectButton, 0);
92              //linkLayout.setComponentAlignment(selectButton, Alignment.MIDDLE_RIGHT);
93          }
94          setButtonCaption(StringUtils.EMPTY);
95          rootLayout.addComponent(linkLayout);
96  
97          this.addValueChangeListener(event -> updateComponents(getValue()));
98  
99          updateComponents(getValue());
100         return rootLayout;
101     }
102 
103     public TextField getTextField() {
104         return this.textField;
105     }
106 
107     public Button getSelectButton() {
108         return this.selectButton;
109     }
110 
111     @Override
112     public String getValue() {
113         return textField.getValue();
114     }
115 
116     @Override
117     public void setReadOnly(boolean readOnly) {
118         super.setReadOnly(readOnly);
119         textField.setReadOnly(readOnly);
120     }
121 
122     @Override
123     protected void doSetValue(String s) {
124         textField.setValue(s);
125     }
126 
127     /**
128      * Update the Link component. <br>
129      * - Set text Field as read only if desired. In this case remove the add button.
130      * - If it is not read only. update the button label.
131      */
132     private void updateComponents(String currentValue) {
133         if (!isFieldEditable && StringUtils.isNotBlank(currentValue)) {
134             textField.setReadOnly(true);
135             if (linkLayout.getComponentIndex(selectButton) != -1) {
136                 linkLayout.removeComponent(selectButton);
137             }
138         } else {
139             setButtonCaption(currentValue);
140         }
141     }
142 
143     private void setButtonCaption(String value) {
144         if (StringUtils.isNotBlank(value)) {
145             selectButton.setCaption(buttonCaptionOther);
146             selectButton.setDescription(buttonCaptionOther);
147         } else {
148             selectButton.setCaption(buttonCaptionNew);
149             selectButton.setDescription(buttonCaptionNew);
150         }
151     }
152 
153     public void setContentPreview(Component contentPreviewComponent) {
154         if (contentPreview != null) {
155             rootLayout.removeComponent(contentPreview);
156         }
157         contentPreviewComponent.setVisible(StringUtils.isNotBlank(textField.getValue()));
158         rootLayout.addComponentAsFirst(contentPreviewComponent);
159         contentPreview = contentPreviewComponent;
160     }
161 
162     /**
163      * Caption section.
164      */
165     public void setButtonCaptionNew(String buttonCaptionNew) {
166         this.buttonCaptionNew = buttonCaptionNew;
167     }
168 
169     public void setButtonCaptionOther(String buttonCaptionOther) {
170         this.buttonCaptionOther = buttonCaptionOther;
171     }
172 
173     public void setFieldEditable(boolean isFieldEditable) {
174         this.isFieldEditable = isFieldEditable;
175     }
176 }