/** @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);
    }
  }
    /** @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);
    }
  /**
   * 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);
  }
  /**
   * 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);
  }
  /**
   * 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();
                }
              });
    }
  }
  /**
   * 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);
  }
  /**
   * 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);
  }
    /**
     * 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);
    }
  /**
   * Sets the title label text.
   *
   * <p>
   *
   * @param label the new title to set
   */
  public void setTitleLabel(String label) {

    m_title.setText(label);
  }
  /**
   * Sets the subtitle label text.
   *
   * <p>
   *
   * @param label the new subtitle to set
   */
  public void setSubtitleLabel(String label) {

    m_subtitle.setText(label);
  }
  /**
   * 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);
  }
  /**
   * Returns the title label text.
   *
   * <p>
   *
   * @return the title label text
   */
  public String getTitleLabel() {

    return m_title.getText();
  }
  /**
   * Returns the subtitle label.
   *
   * <p>
   *
   * @return the subtitle label
   */
  public String getSubtitleLabel() {

    return m_subtitle.getText();
  }
  /**
   * 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);
  }
  /**
   * 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);
  }