Package org.olat.core.gui.components

Source Code of org.olat.core.gui.components.Component

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) 1999-2006 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.core.gui.components;

import java.util.ArrayList;
import java.util.List;

import org.olat.core.gui.UserRequest;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.render.ValidationResult;
import org.olat.core.gui.translator.Translator;
import org.olat.core.logging.AssertException;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.logging.activity.ThreadLocalUserActivityLoggerInstaller;
import org.olat.core.util.CodeHelper;

/**
* Description: <br>
*
* @author Felix Jost
*/
public abstract class Component {

  private static final OLog log_ = Tracing.createLoggerFor(Component.class);

  private boolean spanReplaceable = false;

  private String name;
  private long dispatchID;

  private int timestamp = 1;
 
  private boolean visible = true;
  private boolean enabled = true;
  // true when contents have changed since last rendering
  private boolean dirty = false;
  private boolean domReplaceable = true;

  private List<Controller> listeners;
  private Translator translator;
  // for debugging reasons to trace where the latest dispatch occured
  private Controller latestDispatchedController;
  // for debugging reasons to trace which event was latest fired before an
  // exception
  private Event latestFiredEvent;
  // watch only
 
  /**
   * do not create a logger for this class otherwise millions of useless loggers are created which consumes
   * quite some memory
   */

  private Container parent = null;
  /**
   *
   * @param name the name of this component
   */
  public Component(String name) {
    this(name, null);
  }

  /**
   *
   * @param name the name of this component
   * @param translator the translator
   */
  public Component(String name, Translator translator) {
    dispatchID = CodeHelper.getRAMUniqueID();
    this.name = name;
    this.translator = translator;
    listeners = new ArrayList<Controller>(2);
  }

  /**
   * @return String
   */
  public String getComponentName() {
    return name;
  }

  /**
   * @return boolean
   */
  public boolean isVisible() {
    return visible;
  }

  /**
   * True by default: The component gets rendered<br>
   * false: The componet gets not rendered.
   * Sets the visible.
   *
   * @param visible The visible to set
   */
  public void setVisible(boolean visible) {
    if(visible ^ this.visible){
      this.visible = visible;
      setDirty(true);
    }
  }

  public void dispatchRequest(final UserRequest ureq) {
      doDispatchRequest(ureq);
  }
 
  protected abstract void doDispatchRequest(UserRequest ureq);

  public abstract ComponentRenderer getHTMLRendererSingleton();

  /**
   * called just before the rendering of the -whole tree- takes place, so e.g.
   * lazy fetching can be implemented, or issueing a request for a new moduleUri
   * (e.g. for CPComponent, so that the browser loads images correctly). only
   * called when the component is visible
   */
  public void validate(UserRequest ureq, ValidationResult vr) {
    if (this.dirty) {
      timestamp++;
      if ( Tracing.isDebugEnabled(this.getClass()) ) Tracing.logDebug("increment component.timestamp new value=" + timestamp + " ureq=" + ureq + " component=" + this, this.getClass());
    }
  }
 
  /**
   * fires events to registered listeners of generic events.
   * To see all events set this class and also AbstractEventBus and DefaultController to debug.
   * @param event
   * @param ores
   */
  protected void fireEvent(final UserRequest ureq, final Event event) {
    Controller[] listenerArray = new Controller[listeners.size()];
    listeners.toArray(listenerArray);
   
    for (Controller listenerA:listenerArray) {
      final Controller listener = listenerA;
      latestDispatchedController = listenerA;
      latestFiredEvent = event;
      try{
        listener.getUserActivityLogger().frameworkSetBusinessPathFromWindowControl(listener.getWindowControlForDebug());
      } catch(AssertException e) {
        log_.error("Error in setting up the businessPath on the IUserActivityLogger. listener="+listener, e);
        // still continue
      }
      ThreadLocalUserActivityLoggerInstaller.runWithUserActivityLogger(new Runnable() {

        public void run() {
          listener.dispatchEvent(ureq, Component.this, event);
        }
       
      }, listener.getUserActivityLogger());
      // clear the event for memory reasons, used only for debugging reasons in
      // case of an error
      // TODO:fj: may be useful for admin purposes
      // FIXME:fj:a rework events so we can get useful info out of it
      latestFiredEvent = null;
    }
  }

  /**
   *
   * @return a list of the controllers listening (normally only one)
   */
  public List<Controller> debuginfoGetListeners() {
    return listeners;
  }
 
  /**
   * @param controller
   */
  public void addListener(Controller controller) {
    // tests if the same controller was already registered to avoid
    // double-firing.
    // the contains method is fast since there is normally one one listener
    // (controller) in the listener list.
    if (listeners.contains(controller)) throw new AssertException("controller was already added to component '" + getComponentName()
        + "', controller was: " + controller.toString());
    listeners.add(controller);
  }

  /**
   * @return Translator
   */
  public Translator getTranslator() {
    return translator;
  }

  /**
   * Sets the translator. (for framework internal use)
   *
   * @param translator The translator to set
   */
  protected void setTranslator(Translator translator) {
    this.translator = translator;
  }

  /**
   * @return long the dispatchid (which is assigned at construction time of the component and never changes)
   */
  public long getDispatchID() {
    return dispatchID;
  }

  /**
   * @return the extended debuginfo
   */
  public String getExtendedDebugInfo() {
    // default impl to be overriden
    return "n/a";
  }

  /**
   * @return
   */
  public String getListenerInfo() {
    return "listener:" + listeners.toString();
  }

  /**
   * @see java.lang.Object#toString()
   */
  public String toString() {
    return getComponentName() + " " + super.toString();
  }

  /**
   * true by default: The componet gets rendered and actions get dispatched
   * if false: e.g. @see Link the link gets rendered but is not clickable
   * @return Returns the enabled.
   */
  public boolean isEnabled() {
    return enabled;
  }

  /**
   * @param enabled The enabled to set.
   */
  public void setEnabled(boolean enabled) {
    if(enabled ^ this.enabled) {
      setDirty(true);
    }
    this.enabled = enabled;
  }

  /**
   * only for debug purposes!!!
   *
   * @return Returns the latestDispatchedController.
   */
  public Controller getLatestDispatchedController() {
    return latestDispatchedController;
  }

  /**
   * only for debugging reasons!!!
   *
   * @return Returns the latestFiredEvent.
   */
  public Event getAndClearLatestFiredEvent() {
    Event tmp = latestFiredEvent;
    latestFiredEvent = null; // gc
    return tmp;
  }

  /**
   * @return returns whether the component needs to be rerendered or not
   */
  public boolean isDirty() {
    return dirty;
  }
 
  /**
   * used by the screenreader feature to determine whether the component has changed from a user's perspective.
   * normally this is the same as isDirty(), but may differ, e.g. for a MenuTree (expanding the tree: true; activating a link: false)
   * @see org.olat.core.gui.components.tree.MenuTree
   * @return whether the component has changed from a user's perspective.
   */
  public boolean isDirtyForUser() {
    // default implementation
    return isDirty();
  }

  /**
   * @param dirty The dirty to set.
   */
  public void setDirty(boolean dirty) {
    this.dirty = dirty;
  }

  /**
   * @return Returns the domReplaceable.
   */
  public boolean isDomReplaceable() {
    return domReplaceable;
  }

  /**
   * if set to true(default), then this component can be swapped out in the
   * browser dom tree if that capability is enabled
   *
   * @param domReplaceable The domReplaceable to set.
   */
  public void setDomReplaceable(boolean domReplaceable) {
    this.domReplaceable = domReplaceable;
  }
 
 
  public void setSpanAsDomReplaceable(boolean spanReplaceable){
    this.spanReplaceable = spanReplaceable;
  }
  public boolean getSpanAsDomReplaceable(){
    return this.spanReplaceable;
  }
 
  /**
   * to be called only by the container when a child is added
   * @param parent
   * @deprecated
   */
  void setParent(Container parent){
    this.parent = parent;
  }
 
  /**
   * @return
   */
  public Container getParent(){
    return this.parent;
  }
   
  /**
   * to be used by Window.java to detect browser back in ajax-mode
   * @return Returns the timestamp.
   */
  public int getTimestamp() {
    return timestamp;
  }

}
TOP

Related Classes of org.olat.core.gui.components.Component

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.