/* * 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.ui; import org.opencms.db.CmsResourceState; import org.opencms.gwt.client.CmsCoreProvider; import org.opencms.gwt.client.Messages; import org.opencms.gwt.client.ui.I_CmsButton.ButtonStyle; import org.opencms.gwt.client.ui.css.I_CmsImageBundle; import org.opencms.gwt.client.ui.css.I_CmsInputLayoutBundle; import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle; import org.opencms.gwt.client.ui.css.I_CmsLayoutBundle.I_CmsListItemWidgetCss; import org.opencms.gwt.client.ui.input.CmsLabel; import org.opencms.gwt.client.util.CmsDomUtil; import org.opencms.gwt.client.util.CmsResourceStateUtil; import org.opencms.gwt.client.util.CmsStyleVariable; import org.opencms.gwt.shared.CmsAdditionalInfoBean; import org.opencms.gwt.shared.CmsIconUtil; import org.opencms.gwt.shared.CmsListInfoBean; import org.opencms.gwt.shared.CmsListInfoBean.LockIcon; import org.opencms.gwt.shared.CmsListInfoBean.StateIcon; import org.opencms.util.CmsStringUtil; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.DoubleClickEvent; import com.google.gwt.event.dom.client.DoubleClickHandler; import com.google.gwt.event.dom.client.HasClickHandlers; import com.google.gwt.event.dom.client.HasDoubleClickHandlers; import com.google.gwt.event.dom.client.HasMouseOutHandlers; import com.google.gwt.event.dom.client.HasMouseOverHandlers; import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.logical.shared.HasCloseHandlers; import com.google.gwt.event.logical.shared.HasOpenHandlers; import com.google.gwt.event.logical.shared.OpenEvent; import com.google.gwt.event.logical.shared.OpenHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; /** * Provides a UI list item.<p> * * @since 8.0.0 */ public class CmsListItemWidget extends Composite implements HasOpenHandlers<CmsListItemWidget>, HasCloseHandlers<CmsListItemWidget>, HasMouseOutHandlers, HasClickHandlers, HasDoubleClickHandlers, HasMouseOverHandlers, I_CmsTruncable { /** Additional info item HTML. */ public static class AdditionalInfoItem extends Composite implements I_CmsTruncable { /** Text metrics key. */ private static final String TMA_TITLE = "AddInfoTitle"; /** Text metrics key. */ private static final String TMA_VALUE = "AddInfoValue"; /** The title element. */ private CmsLabel m_titleLabel; /** The value element. */ private CmsLabel m_valueLabel; /** * Constructor.<p> * * @param additionalInfo the info to display */ public AdditionalInfoItem(CmsAdditionalInfoBean additionalInfo) { this(additionalInfo.getName(), additionalInfo.getValue(), additionalInfo.getStyle()); } /** * Constructor.<p> * * @param title info title * @param value info value * @param additionalStyle an additional class name */ public AdditionalInfoItem(String title, String value, String additionalStyle) { super(); FlowPanel panel = new FlowPanel(); initWidget(panel); I_CmsListItemWidgetCss style = I_CmsLayoutBundle.INSTANCE.listItemWidgetCss(); // create title m_titleLabel = new CmsLabel(CmsStringUtil.isEmptyOrWhitespaceOnly(title) ? "" : title + ":"); m_titleLabel.addStyleName(style.itemAdditionalTitle()); panel.add(m_titleLabel); // create value m_valueLabel = new CmsLabel(); if (CmsStringUtil.isEmptyOrWhitespaceOnly(value)) { m_valueLabel.setHTML(CmsDomUtil.Entity.nbsp.html()); } else { m_valueLabel.setHTML(value); } m_valueLabel.addStyleName(style.itemAdditionalValue()); if (additionalStyle != null) { m_valueLabel.addStyleName(additionalStyle); } panel.add(m_valueLabel); } /** * Returns the title element.<p> * * @return the title element */ public CmsLabel getTitleLabel() { return m_titleLabel; } /** * Returns the value element.<p> * * @return the value element */ public CmsLabel getValueLabel() { return m_valueLabel; } /** * @see org.opencms.gwt.client.ui.I_CmsTruncable#truncate(java.lang.String, int) */ public void truncate(String textMetricsPrefix, int widgetWidth) { int titleWidth = widgetWidth / 4; m_titleLabel.truncate(textMetricsPrefix + TMA_TITLE, titleWidth); // the rest m_valueLabel.truncate(textMetricsPrefix + TMA_VALUE, widgetWidth - titleWidth - 15); } } /** Background color values. */ public enum Background { /** Color blue. */ BLUE, /** Default color. */ DEFAULT, /** Color red. */ RED, /** Color yellow. */ YELLOW } /** * The interface for handling edits of the title field.<p> */ public interface I_CmsTitleEditHandler { /** * This method is called when the user has finished editing the title field.<p> * * @param title the label containing the title * @param box the */ void handleEdit(CmsLabel title, TextBox box); } /** * @see com.google.gwt.uibinder.client.UiBinder */ protected interface I_CmsListItemWidgetUiBinder extends UiBinder<CmsHoverPanel, CmsListItemWidget> { // GWT interface, nothing to do here } /** The CSS class to set the additional info open. */ protected static final String OPENCLASS = I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().open(); /** Text metrics key. */ private static final String TM_SUBTITLE = "Subtitle"; /** Text metrics key. */ private static final String TM_TITLE = "Title"; /** The ui-binder instance for this class. */ private static I_CmsListItemWidgetUiBinder uiBinder = GWT.create(I_CmsListItemWidgetUiBinder.class); /** DIV for additional item info. */ @UiField protected FlowPanel m_additionalInfo; /** Panel to hold buttons.*/ @UiField protected FlowPanel m_buttonPanel; /** Panel to hold the content.*/ @UiField protected FlowPanel m_contentPanel; /** A list of click handlers for the main icon. */ protected List<ClickHandler> m_iconClickHandlers = new ArrayList<ClickHandler>(); /** The DIV showing the list icon. */ @UiField protected SimplePanel m_iconPanel; /** The open-close button for the additional info. */ protected CmsPushButton m_openClose; /** Sub title label. */ @UiField protected CmsLabel m_subtitle; /** A label which is optionally displayed after the subtitle. */ protected CmsLabel m_subtitleSuffix; /** Title label. */ @UiField protected CmsLabel m_title; /** The title row, holding the title and the open-close button for the additional info. */ @UiField protected FlowPanel m_titleRow; /** Variable for the background style. */ private CmsStyleVariable m_backgroundStyle; /** The child width in px for truncation. */ private int m_childWidth; /** The fixed icon classes which will always be added if the icon classes are set. */ private String m_fixedIconClasses = ""; /** The event handler registrations. */ private List<HandlerRegistration> m_handlerRegistrations; /** A click handler which triggers all icon click handlers. */ private ClickHandler m_iconSuperClickHandler = new ClickHandler() { public void onClick(ClickEvent event) { for (ClickHandler iconClickHandler : m_iconClickHandlers) { iconClickHandler.onClick(event); } } }; /** The main icon title. */ private String m_iconTitle = ""; /** The lock icon. */ private HTML m_lockIcon; /** The state icon. */ private HTML m_stateIcon; /** The handler registration for the click handler on the title field. */ private HandlerRegistration m_titleClickHandlerRegistration; /** A handler object for handling editing of the title field. */ private I_CmsTitleEditHandler m_titleEditHandler; /** The text metrics prefix. */ private String m_tmPrefix; /** * Constructor. Using a 'li'-tag as default root element.<p> * * @param infoBean bean holding the item information */ public CmsListItemWidget(CmsListInfoBean infoBean) { initWidget(uiBinder.createAndBindUi(this)); m_handlerRegistrations = new ArrayList<HandlerRegistration>(); m_backgroundStyle = new CmsStyleVariable(this); m_subtitleSuffix = new CmsLabel(); m_subtitleSuffix.addStyleName(I_CmsLayoutBundle.INSTANCE.generalCss().inlineBlock()); init(infoBean); } /** * Adds an additional info item to the list.<p> * * @param additionalInfo the additional info to display */ public void addAdditionalInfo(CmsAdditionalInfoBean additionalInfo) { m_additionalInfo.add(new AdditionalInfoItem(additionalInfo)); ensureOpenCloseAdditionalInfo(); } /** * Adds a widget to the button panel.<p> * * @param w the widget to add */ public void addButton(Widget w) { m_buttonPanel.add(w); if (CmsCoreProvider.get().isIe7()) { m_buttonPanel.getElement().getStyle().setWidth(m_buttonPanel.getWidgetCount() * 22, Unit.PX); } } /** * Adds a widget to the front of the button panel.<p> * * @param w the widget to add */ public void addButtonToFront(Widget w) { m_buttonPanel.insert(w, 0); if (CmsCoreProvider.get().isIe7()) { m_buttonPanel.getElement().getStyle().setWidth(m_buttonPanel.getWidgetCount() * 22, Unit.PX); } } /** * @see com.google.gwt.event.dom.client.HasClickHandlers#addClickHandler(ClickHandler) */ public HandlerRegistration addClickHandler(ClickHandler handler) { return addDomHandler(handler, ClickEvent.getType()); } /** * @see com.google.gwt.event.logical.shared.HasCloseHandlers#addCloseHandler(com.google.gwt.event.logical.shared.CloseHandler) */ public HandlerRegistration addCloseHandler(CloseHandler<CmsListItemWidget> handler) { return addHandler(handler, CloseEvent.getType()); } /** * @see com.google.gwt.event.dom.client.HasDoubleClickHandlers#addDoubleClickHandler(com.google.gwt.event.dom.client.DoubleClickHandler) */ public HandlerRegistration addDoubleClickHandler(DoubleClickHandler handler) { return addDomHandler(handler, DoubleClickEvent.getType()); } /** * Adds a mouse click handler to the icon panel.<p> * * @param handler the click handler * * @return the handler registration */ public HandlerRegistration addIconClickHandler(final ClickHandler handler) { final HandlerRegistration internalHandlerRegistration = m_iconPanel.addDomHandler(handler, ClickEvent.getType()); m_iconClickHandlers.add(handler); HandlerRegistration result = new HandlerRegistration() { public void removeHandler() { internalHandlerRegistration.removeHandler(); m_iconClickHandlers.remove(handler); } }; return result; } /** * @see com.google.gwt.event.dom.client.HasMouseOutHandlers#addMouseOutHandler(com.google.gwt.event.dom.client.MouseOutHandler) */ public HandlerRegistration addMouseOutHandler(MouseOutHandler handler) { HandlerRegistration req = addDomHandler(handler, MouseOutEvent.getType()); m_handlerRegistrations.add(req); return req; } /** * @see com.google.gwt.event.dom.client.HasMouseOverHandlers#addMouseOverHandler(com.google.gwt.event.dom.client.MouseOverHandler) */ public HandlerRegistration addMouseOverHandler(MouseOverHandler handler) { HandlerRegistration req = addDomHandler(handler, MouseOverEvent.getType()); m_handlerRegistrations.add(req); return req; } /** * @see com.google.gwt.event.logical.shared.HasOpenHandlers#addOpenHandler(com.google.gwt.event.logical.shared.OpenHandler) */ public HandlerRegistration addOpenHandler(OpenHandler<CmsListItemWidget> handler) { return addHandler(handler, OpenEvent.getType()); } /** * Adds a style name to the subtitle label.<p> * * @param styleName the style name to add */ public void addSubtitleStyleName(String styleName) { m_subtitle.addStyleName(styleName); } /** * Adds a style name to the title label.<p> * * @param styleName the style name to add */ public void addTitleStyleName(String styleName) { m_title.addStyleName(styleName); } /** * Hides the icon of the list item widget.<p> */ public void clearIcon() { m_iconPanel.setVisible(false); } /** * Forces mouse out on self and contained buttons.<p> */ public void forceMouseOut() { for (Widget w : m_buttonPanel) { CmsDomUtil.ensureMouseOut(w); } CmsDomUtil.ensureMouseOut(this); removeStyleName(I_CmsLayoutBundle.INSTANCE.stateCss().cmsHovering()); } /** * Returns the button at the given position.<p> * * @param index the button index * * @return the button at the given position */ public Widget getButton(int index) { return m_buttonPanel.getWidget(index); } /** * Returns the number of buttons.<p> * * @return the number of buttons */ public int getButtonCount() { return m_buttonPanel.getWidgetCount(); } /** * Returns the button panel.<p> * * @return the button panel */ public FlowPanel getButtonPanel() { return m_buttonPanel; } /** * Returns the content panel.<p> * * @return the content panel */ public FlowPanel getContentPanel() { return m_contentPanel; } /** * Returns the subtitle label.<p> * * @return the subtitle label */ public String getSubtitleLabel() { return m_subtitle.getText(); } /** * Returns the label after the subtitle.<p> * * @return the label after the subtitle */ public CmsLabel getSubTitleSuffix() { return m_subtitleSuffix; } /** * Returns the title label text.<p> * * @return the title label text */ public String getTitleLabel() { return m_title.getText(); } /** * Returns if additional info items are present.<p> * * @return <code>true</code> if additional info items are present */ public boolean hasAdditionalInfo() { return m_additionalInfo.getWidgetCount() > 0; } /** * Re-initializes the additional infos.<p> * * @param infoBean the info bean */ public void reInitAdditionalInfo(CmsListInfoBean infoBean) { m_additionalInfo.clear(); if (m_openClose != null) { m_openClose.removeFromParent(); m_openClose = null; } initAdditionalInfo(infoBean); } /** * Removes a widget from the button panel.<p> * * @param w the widget to remove */ public void removeButton(Widget w) { m_buttonPanel.remove(w); if (CmsCoreProvider.get().isIe7()) { m_buttonPanel.getElement().getStyle().setWidth(m_buttonPanel.getWidgetCount() * 22, Unit.PX); } } /** * Removes all registered mouse event handlers including the context menu handler.<p> */ public void removeMouseHandlers() { Iterator<HandlerRegistration> it = m_handlerRegistrations.iterator(); while (it.hasNext()) { it.next().removeHandler(); } m_handlerRegistrations.clear(); } /** * Removes a style name from the subtitle label.<p> * * @param styleName the style name to add */ public void removeSubtitleStyleName(String styleName) { m_subtitle.removeStyleName(styleName); } /** * Removes a style name from the title label.<p> * * @param styleName the style name to add */ public void removeTitleStyleName(String styleName) { m_title.removeStyleName(styleName); } /** * Sets the additional info value label at the given position.<p> * * @param index the additional info index * @param label the new value to set */ public void setAdditionalInfoValue(int index, String label) { ((AdditionalInfoItem)m_additionalInfo.getWidget(index)).getValueLabel().setText(label); } /** * Sets the additional info visible if present.<p> * * @param visible <code>true</code> to show, <code>false</code> to hide */ public void setAdditionalInfoVisible(boolean visible) { if (m_openClose == null) { return; } if (visible) { addStyleName(CmsListItemWidget.OPENCLASS); m_openClose.setDown(true); OpenEvent.fire(this, this); } else { removeStyleName(CmsListItemWidget.OPENCLASS); m_openClose.setDown(false); CloseEvent.fire(this, this); } } /** * Sets the background color.<p> * * @param background the color */ public void setBackground(Background background) { switch (background) { case BLUE: m_backgroundStyle.setValue(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().itemBlue()); break; case RED: m_backgroundStyle.setValue(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().itemRed()); break; case YELLOW: m_backgroundStyle.setValue(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().itemYellow()); break; case DEFAULT: default: m_backgroundStyle.setValue(null); } } /** * Sets the icon of this item.<p> * * @param image the image to use as icon */ public void setIcon(Image image) { m_iconPanel.setVisible(true); if (image == null) { return; } m_iconPanel.setWidget(image); } /** * Sets the icon for this item using the given CSS classes.<p> * * @param iconClasses the CSS classes */ public void setIcon(String iconClasses) { m_iconPanel.setVisible(true); Panel iconWidget = new SimplePanel(); m_iconPanel.setWidget(iconWidget); iconWidget.addStyleName(iconClasses + " " + m_fixedIconClasses); } /** * Sets the icon title.<p> * * @param title the new icon title */ public void setIconTitle(String title) { m_iconTitle = title; m_iconPanel.setTitle(title); } /** * Sets the lock icon.<p> * * @param icon the icon to use * @param iconTitle the icon title */ public void setLockIcon(LockIcon icon, String iconTitle) { if (m_lockIcon == null) { m_lockIcon = new HTML(); m_lockIcon.addClickHandler(m_iconSuperClickHandler); m_contentPanel.add(m_lockIcon); } switch (icon) { case CLOSED: m_lockIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockIcon() + " " + I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockClosed()); break; case OPEN: m_lockIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockIcon() + " " + I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockOpen()); break; case SHARED_CLOSED: m_lockIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockIcon() + " " + I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockSharedClosed()); break; case SHARED_OPEN: m_lockIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockIcon() + " " + I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockSharedOpen()); break; case NONE: default: m_lockIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().lockIcon()); } m_lockIcon.setTitle(concatIconTitles(m_iconTitle, iconTitle)); m_lockIcon.getElement().getStyle().setCursor(Style.Cursor.POINTER); } /** * Sets the state icon.<p> * * The state icon indicates if a resource is exported, secure, etc.<p> * * @param icon the state icon */ public void setStateIcon(StateIcon icon) { if (m_stateIcon == null) { m_stateIcon = new HTML(); m_stateIcon.addClickHandler(m_iconSuperClickHandler); m_contentPanel.add(m_stateIcon); } String iconTitle = null; switch (icon) { case export: m_stateIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().stateIcon() + " " + I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().export()); iconTitle = Messages.get().key(Messages.GUI_ICON_TITLE_EXPORT_0); break; case secure: m_stateIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().stateIcon() + " " + I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().secure()); iconTitle = Messages.get().key(Messages.GUI_ICON_TITLE_SECURE_0); break; default: m_stateIcon.setStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().stateIcon()); break; } m_stateIcon.setTitle(concatIconTitles(m_iconTitle, iconTitle)); m_stateIcon.getElement().getStyle().setCursor(Style.Cursor.POINTER); } /** * Sets the subtitle label text.<p> * * @param label the new subtitle to set */ public void setSubtitleLabel(String label) { m_subtitle.setText(label); } /** * Sets the subtitle suffix text, and hides or displays the subtitle suffix depending on whether * the text is null or not null.<p> * * @param text the text to put into the subtitle suffix */ public void setSubtitleSuffixText(String text) { if (text == null) { if (m_subtitleSuffix.getParent() != null) { m_subtitleSuffix.removeFromParent(); } } else { if (m_subtitleSuffix.getParent() == null) { m_titleRow.add(m_subtitleSuffix); } m_subtitleSuffix.setText(text); } updateTruncation(); } /** * Enables or disabled editing of the title field.<p> * * @param editable if true, makes the title field editable */ public void setTitleEditable(boolean editable) { boolean alreadyEditable = m_titleClickHandlerRegistration != null; if (alreadyEditable == editable) { return; } if (!editable) { m_titleClickHandlerRegistration.removeHandler(); m_titleClickHandlerRegistration = null; } else { m_titleClickHandlerRegistration = m_title.addClickHandler(new ClickHandler() { /** * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) */ public void onClick(ClickEvent event) { editTitle(); } }); } } /** * Sets the handler for editing the list item widget's title. * * @param handler the new title editing handler */ public void setTitleEditHandler(I_CmsTitleEditHandler handler) { m_titleEditHandler = handler; } /** * Sets the title label text.<p> * * @param label the new title to set */ public void setTitleLabel(String label) { m_title.setText(label); } /** * @see org.opencms.gwt.client.ui.I_CmsTruncable#truncate(java.lang.String, int) */ public void truncate(String textMetricsPrefix, int widgetWidth) { m_childWidth = widgetWidth; m_tmPrefix = textMetricsPrefix; int width = widgetWidth - 4; // just to be on the save side if (m_openClose != null) { width -= 16; } if (m_iconPanel.isVisible()) { width -= 32; } if (width < 0) { // IE fails with a JS error if the width is negative width = 0; } m_title.truncate(textMetricsPrefix + TM_TITLE, width - 10); if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_subtitleSuffix.getText())) { m_subtitleSuffix.truncate(textMetricsPrefix + "_STSUFFIX", 100); m_subtitle.truncate(textMetricsPrefix + TM_SUBTITLE, width - 110); } else { m_subtitle.truncate(textMetricsPrefix + TM_SUBTITLE, width - 10); } for (Widget addInfo : m_additionalInfo) { ((AdditionalInfoItem)addInfo).truncate(textMetricsPrefix, widgetWidth - 10); } } /** * Updates the truncation of labels if needed.<p> * * Use after changing any text on the widget.<p> */ public void updateTruncation() { truncate(m_tmPrefix, m_childWidth); } /** * Internal method which is called when the user clicks on an editable title field.<p> */ protected void editTitle() { m_title.setVisible(false); final TextBox box = new TextBox(); box.setText(m_title.getText()); box.getElement().setAttribute("size", "45"); box.addStyleName(I_CmsInputLayoutBundle.INSTANCE.inputCss().labelInput()); box.addStyleName(I_CmsLayoutBundle.INSTANCE.listItemWidgetCss().titleInput()); final String originalTitle = m_title.getText(); // wrap the boolean flag in an array so we can change it from the event handlers final boolean[] checked = new boolean[] {false}; box.addBlurHandler(new BlurHandler() { /** * @see com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event.dom.client.BlurEvent) */ public void onBlur(BlurEvent event) { if (checked[0]) { return; } onEditTitleTextBox(box); checked[0] = true; } }); box.addKeyPressHandler(new KeyPressHandler() { /** * @see com.google.gwt.event.dom.client.KeyPressHandler#onKeyPress(com.google.gwt.event.dom.client.KeyPressEvent) */ public void onKeyPress(KeyPressEvent event) { if (checked[0]) { return; } int keycode = event.getNativeEvent().getKeyCode(); if ((keycode == 10) || (keycode == 13)) { onEditTitleTextBox(box); checked[0] = true; } if (keycode == 27) { box.setText(originalTitle); onEditTitleTextBox(box); checked[0] = true; } } }); m_titleRow.insert(box, 1); box.setFocus(true); } /** * Ensures the open close button for the additional info list is present.<p> */ protected void ensureOpenCloseAdditionalInfo() { if (m_openClose == null) { m_openClose = new CmsPushButton( I_CmsImageBundle.INSTANCE.style().triangleRight(), I_CmsImageBundle.INSTANCE.style().triangleDown()); m_openClose.setButtonStyle(ButtonStyle.TRANSPARENT, null); m_titleRow.insert(m_openClose, 0); m_openClose.addClickHandler(new ClickHandler() { /** * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) */ public void onClick(ClickEvent event) { setAdditionalInfoVisible(!getElement().getClassName().contains(CmsListItemWidget.OPENCLASS)); } }); } } /** * Constructor.<p> * * @param infoBean bean holding the item information */ protected void init(CmsListInfoBean infoBean) { m_iconPanel.setVisible(false); m_title.setText(infoBean.getTitle()); m_subtitle.setText(infoBean.getSubTitle()); // set the resource type icon if present if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(infoBean.getResourceType())) { setIcon(CmsIconUtil.getResourceIconClasses(infoBean.getResourceType(), false)); } if (infoBean.getStateIcon() != null) { setStateIcon(infoBean.getStateIcon()); } if (infoBean.getLockIcon() != null) { setLockIcon(infoBean.getLockIcon(), infoBean.getLockIconTitle()); } initAdditionalInfo(infoBean); } /** * Initializes the additional info.<p> * * @param infoBean the info bean */ protected void initAdditionalInfo(CmsListInfoBean infoBean) { // create the state info CmsResourceState state = infoBean.getResourceState(); if (state != null) { String stateKey = Messages.get().key(Messages.GUI_RESOURCE_STATE_0); String stateValue = CmsResourceStateUtil.getStateName(state); String stateStyle = CmsResourceStateUtil.getStateStyle(state); m_additionalInfo.add(new AdditionalInfoItem(new CmsAdditionalInfoBean(stateKey, stateValue, stateStyle))); ensureOpenCloseAdditionalInfo(); } // set the additional info if (infoBean.hasAdditionalInfo()) { ensureOpenCloseAdditionalInfo(); for (CmsAdditionalInfoBean additionalInfo : infoBean.getAdditionalInfo()) { m_additionalInfo.add(new AdditionalInfoItem(additionalInfo)); } } } /** * Internal method which is called when the user has finished editing the title. * * @param box the text box which has been edited */ protected void onEditTitleTextBox(TextBox box) { if (m_titleEditHandler != null) { m_titleEditHandler.handleEdit(m_title, box); return; } String text = box.getText(); box.removeFromParent(); m_title.setText(text); m_title.setVisible(true); } /** * Combines the main icon title with the title for a status icon overlayed over the main icon.<p> * * @param main the main icon title * @param secondary the secondary icon title * * @return the combined icon title for the secondary icon */ String concatIconTitles(String main, String secondary) { if (main == null) { main = ""; } if (secondary == null) { secondary = ""; } if (secondary.length() == 0) { return main; } return main + " [" + secondary + "]"; } }