001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.acacia.client.widgets.complex; 029 030import org.opencms.acacia.client.css.I_CmsLayoutBundle; 031import org.opencms.acacia.client.widgets.complex.CmsDataViewPreviewWidget.I_ImageProvider; 032import org.opencms.acacia.shared.CmsEntity; 033import org.opencms.gwt.client.util.CmsEmbeddedDialogHandler; 034import org.opencms.gwt.shared.CmsDataViewConstants; 035import org.opencms.gwt.shared.CmsDataViewParamEncoder; 036import org.opencms.util.CmsUUID; 037 038import java.util.ArrayList; 039import java.util.HashMap; 040import java.util.List; 041import java.util.Map; 042 043import com.google.common.collect.Lists; 044import com.google.common.collect.Maps; 045import com.google.gwt.dom.client.Style.Unit; 046import com.google.gwt.event.dom.client.ClickEvent; 047import com.google.gwt.event.dom.client.ClickHandler; 048import com.google.gwt.json.client.JSONArray; 049import com.google.gwt.json.client.JSONObject; 050import com.google.gwt.json.client.JSONParser; 051import com.google.gwt.json.client.JSONString; 052import com.google.gwt.json.client.JSONValue; 053import com.google.gwt.user.client.ui.Composite; 054import com.google.gwt.user.client.ui.Widget; 055 056/** 057 * The client-side widget for data view items.<p> 058 * 059 * This widget by itself doesn't allow you to edit the information directly, 060 * instead it opens a popup window when clicked, in which the user can then select items 061 * from the configured data view.<p> 062 * 063 */ 064public class CmsDataViewClientWidget extends Composite { 065 066 /** The name of the callback. */ 067 public static final String CALLBACK = "cmsDataViewCallback"; 068 069 /** Map of accessors, with their IDs as keys. */ 070 private static Map<String, CmsDataViewValueAccessor> accessors = Maps.newHashMap(); 071 072 /** The entity for which the widget was instantiated. */ 073 private CmsEntity m_entity; 074 075 /** The configuration string. */ 076 private String m_config; 077 078 /** The JSON configuration. */ 079 private JSONObject m_jsonConfig; 080 081 /** Object used to read values from or write them back to the editor. */ 082 private CmsDataViewValueAccessor m_valueAccessor; 083 084 /** 085 * Creates a new instance.<p> 086 * 087 * @param valueAccessor object used to read/write values from and to the editor 088 * @param configString the configuration string 089 */ 090 public CmsDataViewClientWidget(CmsDataViewValueAccessor valueAccessor, String configString) { 091 092 m_valueAccessor = valueAccessor; 093 m_valueAccessor.setWidget(this); 094 095 accessors.put(valueAccessor.getId(), valueAccessor); 096 m_config = configString; 097 098 m_jsonConfig = JSONParser.parseLenient(configString).isObject(); 099 100 Widget widget = createWidget(); 101 initWidget(widget); 102 addStyleName(I_CmsLayoutBundle.INSTANCE.form().widget()); 103 widget.getElement().getStyle().setMarginLeft(-20, Unit.PX); 104 105 ensureCallback(CALLBACK); 106 addDomHandler(new ClickHandler() { 107 108 @SuppressWarnings("synthetic-access") 109 public void onClick(ClickEvent event) { 110 111 m_jsonConfig.put(CmsDataViewConstants.PARAM_CALLBACK, new JSONString(CALLBACK)); 112 m_jsonConfig.put( 113 CmsDataViewConstants.PARAM_CALLBACK_ARG, 114 new JSONString("{" + CmsDataViewConstants.ACCESSOR + ": '" + m_valueAccessor.getId() + "'}")); 115 116 CmsEmbeddedDialogHandler handler = new CmsEmbeddedDialogHandler(); 117 Map<String, String> additionalParams = new HashMap<String, String>(); 118 additionalParams.put( 119 CmsDataViewConstants.PARAM_CONFIG, 120 CmsDataViewParamEncoder.encodeString(m_jsonConfig.toString())); 121 handler.openDialog( 122 CmsDataViewConstants.DATAVIEW_DIALOG, 123 null, 124 new ArrayList<CmsUUID>(), 125 additionalParams); 126 } 127 }, ClickEvent.getType()); 128 } 129 130 /** 131 * Ensures that the javascript callback is installed.<p> 132 * 133 * @param name the name of the callback function 134 */ 135 public static native void ensureCallback(String name) /*-{ 136 if (!($wnd[name])) { 137 $wnd[name] = function(x) { 138 var json = JSON.stringify(x); 139 @org.opencms.acacia.client.widgets.complex.CmsDataViewClientWidget::handleResult(Ljava/lang/String;)(json); 140 }; 141 } 142 }-*/; 143 144 /** 145 * Handles the JSON results returned by the embedded Vaadin dialog.<p> 146 * 147 * @param json the JSON results 148 */ 149 public static void handleResult(String json) { 150 151 JSONObject jsonObj = JSONParser.parseLenient(json).isObject(); 152 JSONArray results = jsonObj.get(CmsDataViewConstants.KEY_RESULT).isArray(); 153 String accessorId = jsonObj.get(CmsDataViewConstants.ACCESSOR).isString().stringValue(); 154 CmsDataViewValueAccessor accessor = accessors.get(accessorId); 155 List<CmsDataViewValue> values = Lists.newArrayList(); 156 for (int i = 0; i < results.size(); i++) { 157 JSONObject singleResult = results.get(i).isObject(); 158 String id = singleResult.get(CmsDataViewConstants.FIELD_ID).isString().stringValue(); 159 String title = singleResult.get(CmsDataViewConstants.FIELD_TITLE).isString().stringValue(); 160 String description = singleResult.get(CmsDataViewConstants.FIELD_DESCRIPTION).isString().stringValue(); 161 String data = singleResult.get(CmsDataViewConstants.FIELD_DATA).isString().stringValue(); 162 CmsDataViewValue value = new CmsDataViewValue(id, title, description, data); 163 values.add(value); 164 } 165 accessor.replaceValue(values); 166 } 167 168 /** 169 * Creates the correct widget based on the configuration.<p> 170 * 171 * @return the new widget 172 */ 173 Widget createWidget() { 174 175 if (isTrue(m_jsonConfig, CmsDataViewConstants.CONFIG_PREVIEW)) { 176 return new CmsDataViewPreviewWidget( 177 m_config, 178 m_valueAccessor, 179 new CmsDataViewPreviewWidget.ContentImageLoader()); 180 } else { 181 I_ImageProvider provider = null; 182 CmsDataViewValue val = m_valueAccessor.getValue(); 183 JSONValue iconVal = m_jsonConfig.get(CmsDataViewConstants.CONFIG_ICON); 184 if ((iconVal != null) && (iconVal.isString() != null)) { 185 provider = new CmsDataViewPreviewWidget.SimpleImageLoader(iconVal.isString().stringValue()); 186 } 187 return new CmsDataViewPreviewWidget(m_config, m_valueAccessor, provider); 188 } 189 190 } 191 192 /** 193 * Checks if a property in a JSON object is either the boolean value 'true' or a string representation of that value.<p> 194 * 195 * @param obj the JSON object 196 * @param property the property name 197 * @return true if the value represents the boolean 'true' 198 */ 199 private boolean isTrue(JSONObject obj, String property) { 200 201 JSONValue val = obj.get(property); 202 if (val == null) { 203 return false; 204 } 205 boolean stringTrue = ((val.isString() != null) && Boolean.parseBoolean(val.isString().stringValue())); 206 boolean boolTrue = ((val.isBoolean() != null) && val.isBoolean().booleanValue()); 207 return stringTrue || boolTrue; 208 } 209}