/* * This library is part of OpenCms - * the Open Source Content Management System * * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * For further information about Alkacon Software, please see the * company website: http://www.alkacon.com * * For further information about OpenCms, please see the * project website: http://www.opencms.org * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.opencms.gwt.client.property; import org.opencms.gwt.client.Messages; import org.opencms.gwt.client.ui.CmsFieldSet; import org.opencms.gwt.client.ui.CmsListItemWidget; import org.opencms.gwt.client.ui.CmsTabbedPanel; import org.opencms.gwt.client.ui.input.I_CmsFormField; import org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel; import org.opencms.gwt.client.ui.input.form.CmsFormDialog; import org.opencms.gwt.client.ui.input.form.CmsInfoBoxFormFieldPanel; import org.opencms.gwt.client.util.CmsDomUtil; import org.opencms.gwt.shared.CmsListInfoBean; import org.opencms.util.CmsStringUtil; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.logical.shared.BeforeSelectionHandler; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.Widget; /** * A tabbed form field container widget.<p> * * @since 8.0.0 */ public class CmsPropertyPanel extends A_CmsFormFieldPanel { /** Layout data key. */ public static final String LD_DISPLAY_VALUE = "displayValue"; /** Layout data key. */ public static final String LD_GROUP = "group"; /** Layout data key. */ public static final String LD_PROPERTY = "property"; /** Tab id for the "individual" tab. */ public static final String TAB_INDIVIDUAL = "individual"; /** Tab id for the "shared" tab. */ public static final String TAB_SHARED = "shared"; /** Tab id for the "simple" tab. */ public static final String TAB_SIMPLE = "simple"; /** The tab panel. */ protected CmsTabbedPanel<Widget> m_tabPanel = new CmsTabbedPanel<Widget>(); /** Multimap of fields by field group. */ private Multimap<String, I_CmsFormField> m_fieldsByGroup = ArrayListMultimap.create(); /** Map from group/tab names to corresponding panels. */ private Map<String, Panel> m_groups = new LinkedHashMap<String, Panel>(); /** Set of fields which should be displayed at the top of the "individual" tab. */ private Set<String> m_individualDisplay = Sets.newHashSet(); /** The "individual" tab. */ private FlowPanel m_individualTab = new FlowPanel(); /** The tab wrapper for the individual tab. */ private FlowPanel m_individualTabWrapper = new FlowPanel(); /** Set of fields which should be displayed at the top of the "shared" tab. */ private Set<String> m_sharedDisplay = Sets.newHashSet(); /** The "shared" tab. */ private FlowPanel m_sharedTab = new FlowPanel(); /** The tab wrapper for the shared tab. */ private FlowPanel m_sharedTabWrapper = new FlowPanel(); /** True if the "shared" tab should be shown. */ private boolean m_showShared; /** The "simple" tab. */ private FlowPanel m_simpleTab = new FlowPanel(); /** The tab wrapper for the simple tab. */ private FlowPanel m_simpleTabWrapper = new FlowPanel(); /** * Creates a new instance.<p> * * @param showShared true if the "shared" tab should be shown * @param info the bean to use for displaying the info item */ public CmsPropertyPanel(boolean showShared, CmsListInfoBean info) { // TODO: replace with dynamic calculation //m_tabPanel.getElement().getStyle().setProperty("minHeight", "300px"); //m_tabPanel.getElement().getStyle().setHeight(600, Unit.PX); CmsListItemWidget liWidget = createListItemWidget(info); m_simpleTabWrapper.add(liWidget); m_simpleTabWrapper.add(m_simpleTab); m_simpleTab.addStyleName(org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.generalCss().cornerAll()); m_simpleTab.addStyleName(org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.INSTANCE.propertiesCss().vfsModeSimplePropertiesBox()); m_sharedTabWrapper.add(createListItemWidget(info)); m_sharedTabWrapper.add(m_sharedTab); m_individualTabWrapper.add(createListItemWidget(info)); m_individualTabWrapper.add(m_individualTab); m_simpleTabWrapper = CmsDomUtil.wrapScrollable(m_simpleTabWrapper); m_sharedTabWrapper = CmsDomUtil.wrapScrollable(m_sharedTabWrapper); m_individualTabWrapper = CmsDomUtil.wrapScrollable(m_individualTabWrapper); m_groups.put(TAB_SIMPLE, m_simpleTab); m_groups.put(TAB_SHARED, m_sharedTab); m_groups.put(TAB_INDIVIDUAL, m_individualTab); m_tabPanel.add(m_simpleTabWrapper, Messages.get().key(Messages.GUI_PROPERTY_TAB_SIMPLE_0)); m_showShared = showShared; if (m_showShared) { m_tabPanel.add(m_individualTabWrapper, Messages.get().key(Messages.GUI_PROPERTY_TAB_STRUCTURE_0)); m_tabPanel.add(m_sharedTabWrapper, Messages.get().key(Messages.GUI_PROPERTY_TAB_RESOURCE_0)); } else { m_tabPanel.add(m_individualTabWrapper, Messages.get().key(Messages.GUI_PROPERTY_TAB_COMPLETE_0)); } initWidget(m_tabPanel); } /** * Adds the {@link BeforeSelectionHandler} for the tab panel.<p> * * @param handler the pre-selection handler */ public void addBeforeSelectionHandler(BeforeSelectionHandler<Integer> handler) { m_tabPanel.addBeforeSelectionHandler(handler); } /** * Clears the tab with the given id.<p> * * @param tabId the id of the tab to clear */ public void clearTab(String tabId) { m_groups.get(tabId).clear(); } /** * @see org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel#getDefaultGroup() */ @Override public String getDefaultGroup() { return TAB_SIMPLE; } /** * Renders a extended tab.<p> * * @param fields the fields to add * @param tab the tab */ public void renderExtendedTab(Collection<I_CmsFormField> fields, FlowPanel tab) { List<CmsFieldSet> result = new ArrayList<CmsFieldSet>(); tab.clear(); String used = Messages.get().key(Messages.GUI_PROPERTY_BLOCK_USED_0); CmsFieldSet usedFieldSet = new CmsFieldSet(); usedFieldSet.setLegend(used); usedFieldSet.setAnimationDuration(50); String unused = Messages.get().key(Messages.GUI_PROPERTY_BLOCK_UNUSED_0); CmsFieldSet unusedFieldSet = new CmsFieldSet(); unusedFieldSet.setOpen(false); unusedFieldSet.setLegend(unused); unusedFieldSet.setAnimationDuration(50); for (I_CmsFormField field : fields) { if (isTop(field)) { usedFieldSet.addContent(createRow(field)); } else { unusedFieldSet.addContent(createRow(field)); } } if (usedFieldSet.getWidgetCount() > 0) { result.add(usedFieldSet); } if (unusedFieldSet.getWidgetCount() > 0) { result.add(unusedFieldSet); } Iterator<CmsFieldSet> iter = result.iterator(); while (iter.hasNext()) { CmsFieldSet fieldSet = iter.next(); if (iter.hasNext()) { fieldSet.getElement().getStyle().setMarginTop(9, Unit.PX); } else { fieldSet.getElement().getStyle().setMarginTop(15, Unit.PX); } tab.add(fieldSet); } } /** * @see org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel#renderFields(java.util.Collection) */ @Override public void renderFields(Collection<I_CmsFormField> fields) { m_fieldsByGroup = getFieldsByGroup(fields); Collection<I_CmsFormField> simpleTabFields = m_fieldsByGroup.get(TAB_SIMPLE); Collection<I_CmsFormField> individualTabFields = m_fieldsByGroup.get(TAB_INDIVIDUAL); Collection<I_CmsFormField> sharedTabfields = m_fieldsByGroup.get(TAB_SHARED); // process simple tab renderSimpleTab(simpleTabFields); // process individual tab m_individualDisplay = preprocessFields(individualTabFields); renderExtendedTab(individualTabFields, m_individualTab); // process shared tab if (m_showShared) { m_sharedDisplay = preprocessFields(sharedTabfields); renderExtendedTab(sharedTabfields, m_sharedTab); } } /** * @see org.opencms.gwt.client.ui.input.form.A_CmsFormFieldPanel#rerenderFields(java.lang.String, java.util.Collection) */ @Override public void rerenderFields(String tab, Collection<I_CmsFormField> fields) { m_fieldsByGroup.removeAll(tab); m_fieldsByGroup.putAll(tab, fields); m_individualDisplay = preprocessFields(m_fieldsByGroup.get(TAB_INDIVIDUAL)); m_sharedDisplay = preprocessFields(m_fieldsByGroup.get(TAB_SHARED)); if (tab.equals(TAB_SIMPLE)) { m_simpleTab.clear(); renderSimpleTab(fields); } else { if (tab.equals(TAB_INDIVIDUAL)) { renderExtendedTab(fields, m_individualTab); } else if (tab.equals(TAB_SHARED)) { renderExtendedTab(fields, m_sharedTab); } } } /** * Creates a list item widget from a list info bean.<p> * * @param info the list info bean * * @return the list item widget */ protected CmsListItemWidget createListItemWidget(CmsListInfoBean info) { CmsListItemWidget result = new CmsListItemWidget(info); result.truncate(CmsInfoBoxFormFieldPanel.TM_INFOBOX, CmsFormDialog.STANDARD_DIALOG_WIDTH - 50); return result; } /** * Returns the tabbed panel.<p> * * @return the tabbed panel */ protected CmsTabbedPanel<Widget> getTabPanel() { return m_tabPanel; } /** * Partitions a collection of fields by group.<p> * * @param fields the collection of fields * * @return a multimap from groups to form fields */ private Multimap<String, I_CmsFormField> getFieldsByGroup(Collection<I_CmsFormField> fields) { Multimap<String, I_CmsFormField> result = ArrayListMultimap.create(); for (I_CmsFormField field : fields) { String group = field.getLayoutData().get(LD_GROUP); result.put(group, field); } return result; } /** * Returns true if the field should be displayed at the top of both the "individual" and "shared" tabs.<p> * * @param field the field to test * * @return true if the field should be displayed at the top */ private boolean isTop(I_CmsFormField field) { String propName = field.getLayoutData().get(LD_PROPERTY); return m_individualDisplay.contains(propName) || m_sharedDisplay.contains(propName); } /** * Preprocesses the fields to find out which fields need to displayed at the top/bottom later.<p> * * @param fields the fields * * @return the set of property names of the preprocessed fields */ private Set<String> preprocessFields(Collection<I_CmsFormField> fields) { Set<String> displaySet = Sets.newHashSet(); for (I_CmsFormField field : fields) { boolean hasValue = !CmsStringUtil.isEmpty(field.getWidget().getApparentValue()); if (hasValue || Boolean.TRUE.toString().equals(field.getLayoutData().get(LD_DISPLAY_VALUE))) { String propName = field.getLayoutData().get(LD_PROPERTY); displaySet.add(propName); } } return displaySet; } /** * Renders the simple tab.<p> * * @param fields the fields to render */ private void renderSimpleTab(Collection<I_CmsFormField> fields) { for (I_CmsFormField field : fields) { m_simpleTab.add(createRow(field)); } } }