001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://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: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://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 m_valueAccessor = valueAccessor; 092 m_valueAccessor.setWidget(this); 093 094 accessors.put(valueAccessor.getId(), valueAccessor); 095 m_config = configString; 096 097 m_jsonConfig = JSONParser.parseLenient(configString).isObject(); 098 099 Widget widget = createWidget(); 100 initWidget(widget); 101 addStyleName(I_CmsLayoutBundle.INSTANCE.form().widget()); 102 widget.getElement().getStyle().setMarginLeft(-20, Unit.PX); 103 104 ensureCallback(CALLBACK); 105 addDomHandler(new ClickHandler() { 106 107 @SuppressWarnings("synthetic-access") 108 public void onClick(ClickEvent event) { 109 110 m_jsonConfig.put(CmsDataViewConstants.PARAM_CALLBACK, new JSONString(CALLBACK)); 111 m_jsonConfig.put( 112 CmsDataViewConstants.PARAM_CALLBACK_ARG, 113 new JSONString("{" + CmsDataViewConstants.ACCESSOR + ": '" + m_valueAccessor.getId() + "'}")); 114 115 CmsEmbeddedDialogHandler handler = new CmsEmbeddedDialogHandler(); 116 Map<String, String> additionalParams = new HashMap<String, String>(); 117 additionalParams.put( 118 CmsDataViewConstants.PARAM_CONFIG, 119 CmsDataViewParamEncoder.encodeString(m_jsonConfig.toString())); 120 handler.openDialog( 121 CmsDataViewConstants.DATAVIEW_DIALOG, 122 null, 123 new ArrayList<CmsUUID>(), 124 additionalParams); 125 } 126 }, ClickEvent.getType()); 127 } 128 129 /** 130 * Ensures that the javascript callback is installed.<p> 131 * 132 * @param name the name of the callback function 133 */ 134 public static native void ensureCallback(String name) /*-{ 135 if (!($wnd[name])) { 136 $wnd[name] = function(x) { 137 var json = JSON.stringify(x); 138 @org.opencms.acacia.client.widgets.complex.CmsDataViewClientWidget::handleResult(Ljava/lang/String;)(json); 139 }; 140 } 141 }-*/; 142 143 /** 144 * Handles the JSON results returned by the embedded Vaadin dialog.<p> 145 * 146 * @param json the JSON results 147 */ 148 public static void handleResult(String json) { 149 150 JSONObject jsonObj = JSONParser.parseLenient(json).isObject(); 151 JSONArray results = jsonObj.get(CmsDataViewConstants.KEY_RESULT).isArray(); 152 String accessorId = jsonObj.get(CmsDataViewConstants.ACCESSOR).isString().stringValue(); 153 CmsDataViewValueAccessor accessor = accessors.get(accessorId); 154 List<CmsDataViewValue> values = Lists.newArrayList(); 155 for (int i = 0; i < results.size(); i++) { 156 JSONObject singleResult = results.get(i).isObject(); 157 String id = singleResult.get(CmsDataViewConstants.FIELD_ID).isString().stringValue(); 158 String title = singleResult.get(CmsDataViewConstants.FIELD_TITLE).isString().stringValue(); 159 String description = singleResult.get(CmsDataViewConstants.FIELD_DESCRIPTION).isString().stringValue(); 160 String data = singleResult.get(CmsDataViewConstants.FIELD_DATA).isString().stringValue(); 161 CmsDataViewValue value = new CmsDataViewValue(id, title, description, data); 162 values.add(value); 163 } 164 accessor.replaceValue(values); 165 } 166 167 /** 168 * Creates the correct widget based on the configuration.<p> 169 * 170 * @return the new widget 171 */ 172 Widget createWidget() { 173 174 if (isTrue(m_jsonConfig, CmsDataViewConstants.CONFIG_PREVIEW)) { 175 return new CmsDataViewPreviewWidget( 176 m_config, 177 m_valueAccessor, 178 new CmsDataViewPreviewWidget.ContentImageLoader()); 179 } else { 180 I_ImageProvider provider = null; 181 CmsDataViewValue val = m_valueAccessor.getValue(); 182 JSONValue iconVal = m_jsonConfig.get(CmsDataViewConstants.CONFIG_ICON); 183 if ((iconVal != null) && (iconVal.isString() != null)) { 184 provider = new CmsDataViewPreviewWidget.SimpleImageLoader(iconVal.isString().stringValue()); 185 } 186 return new CmsDataViewPreviewWidget(m_config, m_valueAccessor, provider); 187 } 188 189 } 190 191 /** 192 * Checks if a property in a JSON object is either the boolean value 'true' or a string representation of that value.<p> 193 * 194 * @param obj the JSON object 195 * @param property the property name 196 * @return true if the value represents the boolean 'true' 197 */ 198 private boolean isTrue(JSONObject obj, String property) { 199 200 JSONValue val = obj.get(property); 201 if (val == null) { 202 return false; 203 } 204 boolean stringTrue = ((val.isString() != null) && Boolean.parseBoolean(val.isString().stringValue())); 205 boolean boolTrue = ((val.isBoolean() != null) && val.isBoolean().booleanValue()); 206 return stringTrue || boolTrue; 207 } 208}