Package com.daikit.daikit4gxt.client.screen

Source Code of com.daikit.daikit4gxt.client.screen.Screen

/**
* Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
*
*         Project home : http://code.daikit.com/daikit4gxt
*
* 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 com.daikit.daikit4gxt.client.screen;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import com.daikit.daikit4gxt.client.DkMain;
import com.daikit.daikit4gxt.client.action.BaseAction;
import com.daikit.daikit4gxt.client.action.standard.BaseReloadCurrentScreenAction;
import com.daikit.daikit4gxt.client.controller.BaseMainController;
import com.daikit.daikit4gxt.client.log.BaseLogger;
import com.daikit.daikit4gxt.client.ui.UIInvalidatable;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.ContentPanel;
import com.sencha.gxt.widget.core.client.TabPanel;
import com.sencha.gxt.widget.core.client.container.Container;
import com.sencha.gxt.widget.core.client.event.AddEvent;
import com.sencha.gxt.widget.core.client.event.AddEvent.AddHandler;


/**
* Methods that should be overridden to provide custom mechanism :<br>
* - {@link #invalidateUi()}<br>
* - {@link #onFullScreenChanged()}<br>
* - {@link #initializeScreen(Object...)}<br>
* - {@link #screenNeedToBeReloadedRegardlessOfSubPanels()}<br>
* - {@link #getReloadScreenAction(boolean, Object...)}<br>
* - {@link #onBeforeScreenShow(Screen)}<br>
* - {@link #onBeforeScreenLeft(BaseAction)}<br>
* - {@link #onBeforeDisconnect(BaseAction)}<br>
*
* @author Thibaut CASELLI
*
*/
public abstract class Screen extends ContentPanel implements UIInvalidatable
{

  protected final BaseLogger log = BaseLogger.getLog(getClass());

  private boolean isFirstReloadAfterShow = true;

  /**
   * Constructor
   */
  public Screen()
  {
    setFillBackgroundColor(true);
    addAddHandler(new RegisterChildrenAddHandler());
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // SUB PANELS
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  protected final List<ScreenSubPanel> subPanels = new ArrayList<ScreenSubPanel>();
  protected final List<UIInvalidatable> uiInvalidateables = new ArrayList<UIInvalidatable>();

  private final void registerSubPanel(final ScreenSubPanel screenSubPanel)
  {
    subPanels.add(screenSubPanel);
  }

  private class RegisterChildrenAddHandler implements AddHandler
  {
    @Override
    public void onAdd(final AddEvent event)
    {
      final Widget addedWidget = event.getWidget();
      recursiveRegisterScreenSubPanel(addedWidget);
    }
  }

  private void recursiveRegisterScreenSubPanel(final Widget widget)
  {
    if (widget instanceof UIInvalidatable && !uiInvalidateables.contains(widget))
    {
      uiInvalidateables.add((UIInvalidatable) widget);
    }

    Container container = null;
    Panel panel = null;
    if (widget instanceof Container)
    {
      container = (Container) widget;
    }
    else if (widget instanceof TabPanel)
    {
      container = ((TabPanel) widget).getContainer();
    }
    else if (widget instanceof Panel)
    {
      panel = (Panel) widget;
    }
    if (panel != null)
    {
      for (final Widget widget2 : (Panel) widget)
      {
        recursiveRegisterScreenSubPanel(widget2);
      }
    }
    else if (container != null)
    {
      container.addAddHandler(new RegisterChildrenAddHandler());
      if (container instanceof ScreenSubPanel)
      {
        final ScreenSubPanel widgetAsScreenSubPanel = (ScreenSubPanel) container;
        if (!subPanels.contains(widgetAsScreenSubPanel))
        {
          Screen.this.registerSubPanel(widgetAsScreenSubPanel);
        }
        widgetAsScreenSubPanel.setParentScreen(Screen.this);
        uiInvalidateables.remove(widgetAsScreenSubPanel);
      }
      for (final Widget widgetChild : container)
      {
        recursiveRegisterScreenSubPanel(widgetChild);
      }
    }
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // INVALIDATE UI
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  /**
   * Method called by invalidateUI action and MainController.invalidateUi(force)
   */
  public final void baseInvalidateUi()
  {
    invalidateUi();
    for (final ScreenSubPanel screenSubPanel : subPanels)
    {
      screenSubPanel.baseInvalidateUi();
    }
    final List<UIInvalidatable> toRemove = new ArrayList<UIInvalidatable>();
    for (final UIInvalidatable invalidateable : uiInvalidateables)
    {
      //      if (invalidateable instanceof Widget && !((Widget) invalidateable).isAttached())
      //      {
      //        toRemove.add(invalidateable);
      //        //        BaseLogger.debug(getClass(), "Remove UIInvalidateable : " + invalidateable);
      //      }
      //      else
      //      {
      invalidateable.invalidateUi();
      //      }
    }
    uiInvalidateables.removeAll(toRemove);
    isFirstReloadAfterShow = false;
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // ON FULL SCREEN CHANGED
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  /**
   * Method to be overridden to provide custom behavior when the full screen status changed.
   */
  public void onFullScreenChanged()
  {
    // Nothing done by default
  }

  /**
   * Method called by the {@link BaseMainController} when the full screen status changed.
   */
  public final void baseOnFullScreenChanged()
  {
    onFullScreenChanged();
    for (final ScreenSubPanel screenSubPanel : subPanels)
    {
      screenSubPanel.onFullScreenChanged();
    }
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // INITIALIZE SCREEN ACTIONS
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  public void initializeScreen(final Object... args)
  {
    // Nothing done by default
  }

  public final BaseAction<?> getBaseInitializeScreenAction(final Object... args)
  {
    final BaseAction<Void> ret = new BaseAction<Void>(DkMain.i18n().action_initialize_screen_loading_label(), true)
    {
      @Override
      protected void run()
      {
        initializeScreen(args);
        Collections.sort(subPanels);
        for (final ScreenSubPanel screenSubPanel : subPanels)
        {
          screenSubPanel.initializeScreenSubPanel(args);
        }
        onSuccess();
      }
    };
    return ret;
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // RELOAD SCREEN ACTIONS
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  protected boolean screenNeedToBeReloadedRegardlessOfSubPanels()
  {
    return true;
  }

  public final boolean screenOrSubPanelNeedToBeReloaded()
  {
    boolean needToBeReloaded = screenNeedToBeReloadedRegardlessOfSubPanels();
    final Iterator<ScreenSubPanel> it = subPanels.iterator();
    while (!needToBeReloaded && it.hasNext())
    {
      if (it.next().needToBeReloaded())
      {
        needToBeReloaded = true;
      }
    }
    return needToBeReloaded;
  }

  public abstract BaseAction<?> getReloadScreenAction(final boolean force, final Object... optionalArgs);

  public BaseAction<?> getEndOfReloadScreenAction(final boolean force, final Object... optionalArgs)
  {
    // Nothing done by default
    return null;
  }

  /**
   * Method called in the {@link BaseReloadCurrentScreenAction} chain. This action chain is initiated by the
   * {@link MainController} and is intended to provide a refresh of the current screen.
   *
   * @return The {@link BaseAction} created.
   */
  public final BaseAction<?> getBaseReloadScreenAction(final boolean force, final Object... optionalArgs)
  {
    BaseAction<?> ret = null;
    if (force || screenOrSubPanelNeedToBeReloaded())
    {
      // Create Reload action
      final List<BaseAction<?>> actionsReload = new ArrayList<BaseAction<?>>();
      final BaseAction<?> actionReloadScreen = getReloadScreenAction(force, optionalArgs);
      if (actionReloadScreen != null)
      {
        actionsReload.add(actionReloadScreen);
      }
      for (final ScreenSubPanel screenSubPanel : subPanels)
      {
        if (force || screenSubPanel.needToBeReloaded())
        {
          final BaseAction<?> actionReloadScreenSubPanel = screenSubPanel.getReloadSubPanelAction(force, optionalArgs);
          if (actionReloadScreenSubPanel != null)
          {
            actionsReload.add(actionReloadScreenSubPanel);
          }
        }
      }
      // Create chain action.
      for (final BaseAction<?> baseAction : actionsReload)
      {
        if (ret == null)
        {
          ret = baseAction;
        }
        else
        {
          ret.setLastChainAction(baseAction);
        }
      }
    }
    return ret;
  }

  /**
   * Method called in the {@link BaseReloadCurrentScreenAction} chain. This action chain is initiated by the
   * {@link MainController} and is intended to provide the action chain to be executed once the screen has been
   * reloaded. This will be executed after the common invalidateUi action.
   *
   * @return The {@link BaseAction} created.
   */
  public final BaseAction<?> getBaseEndOfReloadScreenAction(final boolean force, final Object... optionalArgs)
  {
    BaseAction<?> ret = null;
    if (force || screenOrSubPanelNeedToBeReloaded())
    {
      // Create end of reload action
      final List<BaseAction<?>> actionsEndOfReload = new ArrayList<BaseAction<?>>();
      final BaseAction<?> actionEndOfReloadScreen = getEndOfReloadScreenAction(force, optionalArgs);
      if (actionEndOfReloadScreen != null)
      {
        actionsEndOfReload.add(actionEndOfReloadScreen);
      }
      for (final ScreenSubPanel screenSubPanel : subPanels)
      {
        if (force || screenSubPanel.needToBeReloaded())
        {
          final BaseAction<?> actionEndOfReloadScreenSubPanel = screenSubPanel.getEndOfReloadScreenActionForSubPanel(force,
              optionalArgs);
          if (actionEndOfReloadScreenSubPanel != null)
          {
            actionsEndOfReload.add(actionEndOfReloadScreenSubPanel);
          }
        }
      }
      for (final BaseAction<?> baseAction : actionsEndOfReload)
      {
        if (ret == null)
        {
          ret = baseAction;
        }
        else
        {
          ret.setLastChainAction(baseAction);
        }
      }
    }
    return ret;
  }

  public final boolean isFirstReloadAfterShow()
  {
    return isFirstReloadAfterShow;
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // CALLBACKS BEFORE SCREEN SHOW / LEFT OR DISCONNECT
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  /**
   * Function called before this screen is shown. After the call to this function the mainController.currentScreen is
   * set to this and the show screen process (layout and chain actions) is done.
   *
   * @param previousDisplayedScreen
   *           the previously displayed screen.
   * @param optionalArgs
   *           optional arguments
   */
  public void onBeforeScreenShow(final Screen previousDisplayedScreen, final Object... optionalArgs)
  {
    // nothing done by default.
  }

  /**
   * Function called when this screen is asked to be left.
   *
   * @return whether or not this screen can be left. If return is false, the screen won't be left and the current
   *         action will be stopped.
   * @param currentAction
   *           the current chain action. To be able to restart it after.
   */
  public boolean onBeforeScreenLeft(final BaseAction<?> currentAction)
  {
    // nothing done by default.
    return true;
  }

  /**
   * Function called before a refresh screen process is initiated. This method is only called if the screen refresh is
   * initiated from the {@link BaseMainController#refreshScreen(boolean, Object...)} or
   * {@link BaseMainController#refreshScreen()} method. Not if the refresh screen is initiated directly from the
   * {@link BaseReloadCurrentScreenAction} inside any action chain.
   *
   * @param currentRefreshAction
   *           the current refresh screen chain action. To be able to execute it after a potential asynchronous action.
   * @return whether or not this screen can be refreshed. If return is false, the screen won't be refreshed and the
   *         current refresh screen action will be aborted.
   */
  public boolean onBeforeScreenRefresh(final BaseAction<?> currentRefreshAction)
  {
    // nothing done by default
    return true;
  }

  /**
   * Method called by the {@link BaseMainController#onScreenBeforeShow(Screen, Object...)} and not intended to be
   * called anywhere else. Use {@link #onBeforeScreenShow(Screen)} instead.
   *
   * @param previousDisplayedScreen
   *           the previously displayed screen.
   * @param optionalArgs
   *           optional arguments
   */
  public final void baseBeforeScreenShow(final Screen previousDisplayedScreen, final Object... optionalArgs)
  {
    isFirstReloadAfterShow = true;
    onBeforeScreenShow(previousDisplayedScreen, optionalArgs);
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // UTILS
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  @Override
  public String toString()
  {
    final StringBuffer sb = new StringBuffer(1000);
    sb.append("(" + this.getClass().getName() + ":heading=").append(getTitle());
    return sb.append(")").toString();
  }

  public void setFillBackgroundColor(final boolean fill)
  {
    if (fill)
    {
      addStyleName("fill-background-color");
    }
    else
    {
      removeStyleName("fill-background-color");
    }
  }

  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
  // DISCONNECTION IN CASE OF STANDALONE APPLICATIONS
  // *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-

  /**
   * Function called when the user want to get disconnected.
   *
   * @return whether or not the user can disconnect. If return is false, the user won't disconnect and the current
   *         action will be stopped.
   * @param the
   *           current chain action. To be able to restart it after.
   */
  public boolean onBeforeDisconnect(final BaseAction<?> currentAction)
  {
    // nothing done by default.
    return true;
  }
}
TOP

Related Classes of com.daikit.daikit4gxt.client.screen.Screen

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.