001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (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.gwt.client.ui.resourceinfo; 029 030import org.opencms.gwt.client.CmsCoreProvider; 031import org.opencms.gwt.client.CmsEditableData; 032import org.opencms.gwt.client.I_CmsDescendantResizeHandler; 033import org.opencms.gwt.client.Messages; 034import org.opencms.gwt.client.ui.CmsFieldSet; 035import org.opencms.gwt.client.ui.CmsList; 036import org.opencms.gwt.client.ui.CmsListItem; 037import org.opencms.gwt.client.ui.CmsListItemWidget; 038import org.opencms.gwt.client.ui.CmsPopup; 039import org.opencms.gwt.client.ui.CmsPushButton; 040import org.opencms.gwt.client.ui.CmsScrollPanel; 041import org.opencms.gwt.client.ui.CmsSimpleListItem; 042import org.opencms.gwt.client.ui.I_CmsButton; 043import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle; 044import org.opencms.gwt.client.ui.contenteditor.CmsContentEditorDialog; 045import org.opencms.gwt.client.ui.contenteditor.CmsContentEditorDialog.DialogOptions; 046import org.opencms.gwt.client.ui.contenteditor.I_CmsContentEditorHandler; 047import org.opencms.gwt.client.ui.contextmenu.CmsContextMenuButton; 048import org.opencms.gwt.client.ui.contextmenu.CmsContextMenuHandler; 049import org.opencms.gwt.client.ui.contextmenu.CmsLogout; 050import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; 051import org.opencms.gwt.client.util.CmsDomUtil; 052import org.opencms.gwt.shared.CmsCoreData.AdeContext; 053import org.opencms.gwt.shared.CmsGwtConstants; 054import org.opencms.gwt.shared.CmsResourceStatusBean; 055import org.opencms.gwt.shared.CmsResourceStatusRelationBean; 056import org.opencms.util.CmsStringUtil; 057import org.opencms.util.CmsUUID; 058 059import java.util.ArrayList; 060import java.util.HashSet; 061import java.util.List; 062import java.util.Set; 063 064import com.google.gwt.core.client.GWT; 065import com.google.gwt.dom.client.Style; 066import com.google.gwt.dom.client.Style.Cursor; 067import com.google.gwt.event.dom.client.ClickEvent; 068import com.google.gwt.event.dom.client.ClickHandler; 069import com.google.gwt.event.logical.shared.CloseEvent; 070import com.google.gwt.event.logical.shared.CloseHandler; 071import com.google.gwt.event.logical.shared.OpenEvent; 072import com.google.gwt.event.logical.shared.OpenHandler; 073import com.google.gwt.user.client.Timer; 074import com.google.gwt.user.client.Window; 075import com.google.gwt.user.client.ui.Composite; 076import com.google.gwt.user.client.ui.FlowPanel; 077import com.google.gwt.user.client.ui.Label; 078import com.google.gwt.user.client.ui.SimplePanel; 079 080/** 081 * Widget which shows which contents refer to a resource. <p> 082 */ 083public class CmsResourceRelationView extends Composite implements I_CmsDescendantResizeHandler { 084 085 /** Enum for the display mode. */ 086 public enum Mode { 087 /** Display siblings. */ 088 siblings, 089 /** Display relation sources. */ 090 sources, 091 092 /** Display relation targets. */ 093 targets 094 } 095 096 /** Set of context menu actions which we do not want to appear in the context menu for the relation source items. */ 097 protected static Set<String> m_filteredActions = new HashSet<String>(); 098 099 /** The detail container path pattern. */ 100 private static final String DETAIL_CONTAINER_PATTERN = ".*\\/\\.detailContainers\\/.*"; 101 102 static { 103 m_filteredActions.add(CmsGwtConstants.ACTION_TEMPLATECONTEXTS); 104 m_filteredActions.add(CmsGwtConstants.ACTION_EDITSMALLELEMENTS); 105 m_filteredActions.add(CmsGwtConstants.ACTION_SELECTELEMENTVIEW); 106 m_filteredActions.add(CmsLogout.class.getName()); 107 } 108 109 /** The panel containing the resource boxes. */ 110 protected CmsList<CmsListItem> m_list; 111 112 /** List for relations from other sites. */ 113 protected CmsList<CmsListItem> m_otherSitesList; 114 115 /** Main panel. */ 116 protected FlowPanel m_panel = new FlowPanel(); 117 118 /** The popup which contains this widget. */ 119 protected CmsPopup m_popup; 120 121 /** The dialog scroll panels. */ 122 List<CmsScrollPanel> m_scrollPanels; 123 124 /** The edit button. */ 125 private CmsPushButton m_editButton; 126 127 /** The context menu handler. */ 128 private CmsContextMenuHandler m_menuHandler; 129 130 /** The display mode. */ 131 private Mode m_mode; 132 133 /** The resource status from which we get the related resources to display. */ 134 private CmsResourceStatusBean m_statusBean; 135 136 /** 137 * Creates a new widget instance.<p> 138 * 139 * @param status the resource status from which we get the related resources to display. 140 * @param mode the display mode (display relation sources or targets) 141 * @param menuHandler the context menu handler 142 */ 143 public CmsResourceRelationView(CmsResourceStatusBean status, Mode mode, CmsContextMenuHandler menuHandler) { 144 145 initWidget(m_panel); 146 m_menuHandler = menuHandler; 147 m_scrollPanels = new ArrayList<CmsScrollPanel>(); 148 m_statusBean = status; 149 m_mode = mode; 150 initContent(status); 151 } 152 153 /** 154 * Initializes the content.<p> 155 * 156 * @param status the status data 157 */ 158 public void initContent(CmsResourceStatusBean status) { 159 160 m_statusBean = status; 161 m_panel.clear(); 162 m_scrollPanels.clear(); 163 164 // wrap list info item in another panel to achieve layout uniformity with other similar widgets 165 SimplePanel infoBoxPanel = new SimplePanel(); 166 infoBoxPanel.getElement().getStyle().setMarginTop(2, Style.Unit.PX); 167 CmsListItemWidget infoWidget = new CmsListItemWidget(status.getListInfo()); 168 infoWidget.addOpenHandler(new OpenHandler<CmsListItemWidget>() { 169 170 public void onOpen(OpenEvent<CmsListItemWidget> event) { 171 172 CmsDomUtil.resizeAncestor(getParent()); 173 } 174 }); 175 infoWidget.addCloseHandler(new CloseHandler<CmsListItemWidget>() { 176 177 public void onClose(CloseEvent<CmsListItemWidget> event) { 178 179 CmsDomUtil.resizeAncestor(getParent()); 180 } 181 }); 182 CmsContextMenuButton menuButton = new CmsContextMenuButton( 183 status.getStructureId(), 184 m_menuHandler, 185 AdeContext.resourceinfo); 186 menuButton.addStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().permaVisible()); 187 infoWidget.addButton(menuButton); 188 m_panel.add(infoBoxPanel); 189 infoBoxPanel.add(infoWidget); 190 m_list = createList(getLegend()); 191 fill(); 192 } 193 194 /** 195 * @see org.opencms.gwt.client.I_CmsDescendantResizeHandler#onResizeDescendant() 196 */ 197 public void onResizeDescendant() { 198 199 Timer timer = new Timer() { 200 201 @Override 202 public void run() { 203 204 for (CmsScrollPanel panel : m_scrollPanels) { 205 panel.onResizeDescendant(); 206 } 207 208 } 209 }; 210 timer.schedule(100); 211 } 212 213 /** 214 * Sets the popup which contains this widget.<p> 215 * 216 * @param popup the popup 217 */ 218 public void setPopup(CmsPopup popup) { 219 220 m_popup = popup; 221 } 222 223 /** 224 * Creates and renders the resource boxes for the related resources.<p> 225 */ 226 protected void fill() { 227 228 m_list.clear(); 229 List<CmsResourceStatusRelationBean> relationBeans = getRelationBeans(); 230 if (relationBeans.isEmpty()) { 231 CmsSimpleListItem item = new CmsSimpleListItem(); 232 item.add(new Label(getEmptyMessage())); 233 m_list.add(item); 234 } else { 235 for (CmsResourceStatusRelationBean relationBean : relationBeans) { 236 CmsListItemWidget itemWidget = new CmsListItemWidget(relationBean.getInfoBean()); 237 CmsListItem item = new CmsListItem(itemWidget); 238 CmsContextMenuButton button = new CmsContextMenuButton( 239 relationBean.getStructureId(), 240 m_menuHandler, 241 AdeContext.resourceinfo); 242 item.getListItemWidget().addButton(button); 243 final CmsResourceStatusRelationBean currentRelationBean = relationBean; 244 final boolean isContainerpage = CmsGwtConstants.TYPE_CONTAINERPAGE.equals( 245 relationBean.getInfoBean().getResourceType()); 246 final boolean isXmlContent = relationBean.isXmlContent(); 247 final boolean isEditable = (isXmlContent || isContainerpage) 248 && relationBean.getPermissionInfo().hasWritePermission() 249 && !currentRelationBean.getSitePath().matches(DETAIL_CONTAINER_PATTERN); 250 if (isEditable) { 251 252 m_editButton = new CmsPushButton(); 253 m_editButton.setImageClass(I_CmsButton.PEN_SMALL); 254 m_editButton.setButtonStyle(ButtonStyle.FONT_ICON, null); 255 m_editButton.setTitle( 256 org.opencms.gwt.client.Messages.get().key( 257 org.opencms.gwt.client.Messages.GUI_BUTTON_ELEMENT_EDIT_0)); 258 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(relationBean.getPermissionInfo().getNoEditReason())) { 259 m_editButton.disable(relationBean.getPermissionInfo().getNoEditReason()); 260 } else { 261 m_editButton.setEnabled(true); 262 } 263 item.getListItemWidget().addButton(m_editButton); 264 m_editButton.addClickHandler(new ClickHandler() { 265 266 public void onClick(ClickEvent event) { 267 268 if (isContainerpage) { 269 Window.open(currentRelationBean.getLink(), "_self", ""); 270 } else { 271 CmsEditableData editableData = new CmsEditableData(); 272 editableData.setElementLanguage(CmsCoreProvider.get().getLocale()); 273 editableData.setStructureId(currentRelationBean.getStructureId()); 274 editableData.setSitePath(currentRelationBean.getSitePath()); 275 CmsContentEditorDialog.get().openEditDialog( 276 editableData, 277 false, 278 null, 279 new DialogOptions(), 280 new I_CmsContentEditorHandler() { 281 282 public void onClose( 283 String sitePath, 284 CmsUUID structureId, 285 boolean isNew, 286 boolean hasChangedSettings, 287 boolean usedPublishDialog) { 288 289 if (m_popup != null) { 290 m_popup.hide(); 291 } 292 } 293 }); 294 ((CmsPushButton)event.getSource()).clearHoverState(); 295 } 296 } 297 }); 298 } 299 300 if (isContainerpage) { 301 if (relationBean.getLink() != null) { 302 final String link = relationBean.getLink(); 303 itemWidget.setIconCursor(Cursor.POINTER); 304 itemWidget.addIconClickHandler(new ClickHandler() { 305 306 public void onClick(ClickEvent e) { 307 308 Window.open(link, "_blank", ""); 309 } 310 }); 311 } 312 } 313 m_list.add(item); 314 } 315 } 316 if ((m_mode == Mode.sources) && !m_statusBean.getOtherSiteRelationSources().isEmpty()) { 317 m_otherSitesList = createList(Messages.get().key(Messages.GUI_RESOURCEINFO_OTHERSITES_LEGEND_0)); 318 for (CmsResourceStatusRelationBean relationBean : m_statusBean.getOtherSiteRelationSources()) { 319 CmsListItemWidget itemWidget = new CmsListItemWidget(relationBean.getInfoBean()); 320 CmsListItem item = new CmsListItem(itemWidget); 321 m_otherSitesList.add(item); 322 } 323 } 324 325 m_list.truncate("RES_INFO", CmsPopup.DEFAULT_WIDTH - 5); 326 if (m_otherSitesList != null) { 327 m_otherSitesList.truncate("RES_INFO", CmsPopup.DEFAULT_WIDTH - 5); 328 } 329 330 } 331 332 /** 333 * Creates a relation item list wrapped in a field set and appends it to the dialog panel.<p> 334 * 335 * @param label the list label 336 * 337 * @return the list 338 */ 339 private CmsList<CmsListItem> createList(String label) { 340 341 CmsFieldSet fieldset = new CmsFieldSet(); 342 CmsScrollPanel scrollPanel = GWT.create(CmsScrollPanel.class); 343 CmsList<CmsListItem> list = new CmsList<CmsListItem>(); 344 scrollPanel.add(list); 345 m_scrollPanels.add(scrollPanel); 346 fieldset.getElement().getStyle().setMarginTop(10, Style.Unit.PX); 347 scrollPanel.getElement().getStyle().setHeight(CmsResourceInfoDialog.SCROLLPANEL_HEIGHT, Style.Unit.PX); 348 fieldset.setLegend(label); 349 fieldset.add(scrollPanel); 350 m_panel.add(fieldset); 351 return list; 352 } 353 354 /** 355 * Gets the message to use for an empty relation list.<p> 356 * 357 * @return the message to display for an empty relation list 358 */ 359 private String getEmptyMessage() { 360 361 switch (m_mode) { 362 case sources: 363 if (m_statusBean.getSourcesError() != null) { 364 return m_statusBean.getSourcesError(); 365 } 366 return org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_USAGE_EMPTY_0); 367 case targets: 368 if (m_statusBean.getTargetsError() != null) { 369 return m_statusBean.getTargetsError(); 370 } 371 //$FALL-THROUGH$ 372 default: 373 return org.opencms.gwt.client.Messages.get().key(org.opencms.gwt.client.Messages.GUI_TARGETS_EMPTY_0); 374 } 375 376 } 377 378 /** 379 * Gets the label to use for the fieldset.<p> 380 * 381 * @return the label for the fieldset 382 */ 383 private String getLegend() { 384 385 switch (m_mode) { 386 case sources: 387 return org.opencms.gwt.client.Messages.get().key( 388 org.opencms.gwt.client.Messages.GUI_RESOURCE_INFO_TAB_USAGE_0); 389 case targets: 390 391 return org.opencms.gwt.client.Messages.get().key( 392 org.opencms.gwt.client.Messages.GUI_RESOURCE_INFO_TAB_TARGETS_0); 393 case siblings: 394 default: 395 return org.opencms.gwt.client.Messages.get().key( 396 org.opencms.gwt.client.Messages.GUI_RESOURCE_INFO_TAB_SIBLINGS_0); 397 398 } 399 400 } 401 402 /** 403 * Gets the relation beans to display.<p> 404 * 405 * @return the list of relation beans to display 406 */ 407 private ArrayList<CmsResourceStatusRelationBean> getRelationBeans() { 408 409 switch (m_mode) { 410 case targets: 411 return m_statusBean.getRelationTargets(); 412 case sources: 413 return m_statusBean.getRelationSources(); 414 case siblings: 415 default: 416 return m_statusBean.getSiblings(); 417 } 418 } 419}