content: /**
   * Copyright 2014 55 Minutes (http://www.55minutes.com)
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package fiftyfive.wicket.basic;
  
  import fiftyfive.wicket.util.Shortcuts;
  import org.apache.wicket.markup.ComponentTag;
  import org.apache.wicket.markup.MarkupStream;
  import org.apache.wicket.markup.html.basic.Label;
  import org.apache.wicket.model.IModel;
  import org.apache.wicket.model.Model;
  
  
  /**
   * An extension of Wicket's Label component that allows a placeholder value to
   * be specified. If the label's default model is empty, then:
   * <ul>
   * <li>A CSS class of "empty" will be added to the tag</li>
   * <li>The placeholder value (if one is specified) will be emitted as the
   * body of the tag</li>
   * </ul>
   * <p>
   * If the model is not empty, this behaves like the standard Label.
   * <p>
   * Example usage:
   * <pre class="example">
   * &lt;span wicket:id="label"&gt;Sample&lt;/span&gt;
   * 
   * IModel&lt;String&gt; emptyModel = null;
   * add(new LabelWithPlaceholder("label", emptyModel).setPlaceholder("N/A"));</pre>
   * <p>
   * Since the model in this example is null, the placeholder will be used,
   * resulting in this output:
   * <pre class="example">
   * &lt;span class="empty"&gt;N/A&lt;/span&gt;</pre>
   * <p>
   * Notice also that {@code class="empty"} has been added.
   *
   * @see #setPlaceholder
   * @see Label
   * @since 2.0
   */
  public class LabelWithPlaceholder extends Label
  {
      private IModel<?> placeholderValue;
      
      /**
       * @see Label#Label(String)
       */
      public LabelWithPlaceholder(final String id)
      {
          this(id, (IModel) null);
      }
  
      /**
       * @see Label#Label(String, String)
       */
      public LabelWithPlaceholder(final String id, String label)
      {
          this(id, new Model(label));
      }
  
      /**
       * @see Label#Label(String, IModel)
       */
      public LabelWithPlaceholder(final String id, IModel<?> model)
      {
          super(id, model);
          add(Shortcuts.cssClass(Shortcuts.prop(this, "cssClass")));
      }
      
      /**
       * Returns "empty" if the value provided by this label's model is empty.
       * Otherwise returns {@code null}.
       */
      public String getCssClass()
      {
          return isEmpty() ? "empty" : null;
      }
      
      /**
       * Sets the value that will be used if the value provided by the
       * model is empty.
       * Note that this value will be escaped based on the label's
       * {@link Label#getEscapeModelStrings() getEscapeModelStrings()} flag.
       */
      public LabelWithPlaceholder setPlaceholder(String valueIfEmpty)
      {
          return setPlaceholder(Model.of(valueIfEmpty));
      }
      
      /**
       * Sets the value that will be used if the value provided by the label's
       * normal model is empty. For localization, consider passing in an
       * instance of Wicket's StringResourceModel.
       * Note that this value will be escaped based on the label's
       * {@link Label#getEscapeModelStrings() getEscapeModelStrings()} flag.
       */
      public LabelWithPlaceholder setPlaceholder(IModel<?> valueIfEmpty)
      {
          this.placeholderValue = valueIfEmpty;
          return this;
      }
      
      /**
       * Returns <code>true</code> if the model of this label is empty.
       * @see Shortcuts#empty
       */
      public boolean isEmpty()
      {
          return Shortcuts.empty(internalGetDefaultModelObjectAsString());
      }
      
      /**
       * Detaches the model that holds the placeholder value.
       */
      @Override
      protected void onDetach()
      {
          if(null != this.placeholderValue) this.placeholderValue.detach();
          super.onDetach();
      }
  
      /**
       * Renders the label using the string value of the model as the tag body.
       * If the value of the model is empty and placeholder was provided by
       * {@link #setPlaceholder}, use the placeholder instead.
       * @see Shortcuts#empty
       */
      @Override
      public void onComponentTagBody(MarkupStream markupStream,
                                     ComponentTag openTag)
      {
          String str = internalGetDefaultModelObjectAsString();
          if(this.placeholderValue != null && Shortcuts.empty(str))
          {
              str = getDefaultModelObjectAsString(this.placeholderValue.getObject());
          }
          replaceComponentTagBody(markupStream, openTag, str);
      }
      
      /**
       * A wrapper for {@link #getDefaultModelObjectAsString()} that can be
       * overridden by subclasses.
       */
      protected String internalGetDefaultModelObjectAsString()
      {
          return getDefaultModelObjectAsString();
      }
  }
  