Package de.esoco.j2me.ui

Source Code of de.esoco.j2me.ui.ScreenManager

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// J2ME-Lib source file
// Copyright (c) 2006 Elmar Sonnenschein / esoco GmbH
// Last Change: 05.11.2006 by eso
//
// J2ME-Lib 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.
//
// J2ME-Lib 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.
//
// You should have received a copy of the GNU Lesser General Public License
// along with J2ME-Lib; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA or use the contact
// information from the GNU website http://www.gnu.org
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
package de.esoco.j2me.ui;

import de.esoco.j2me.J2meLib;
import de.esoco.j2me.midlet.BasicMidlet;
import de.esoco.j2me.util.Log;

import java.util.Stack;

import javax.microedition.lcdui.Displayable;


/********************************************************************
* Manages the Displayable screens visible on a MIDlet display. This class
* provides several static methods that coordinate multithreaded access to the
* display. Multiple screens are managed in form of a stack, i.e. the last
* screen added with the method {@link #show(Displayable)} will be on top of the
* stack. This allows applications with multiple screens to delegate part of
* their screen management to the ScreenManager class. That is especially useful
* if multiple threads are involved in displaying the application screens.
*
* <p>The screen manager distinguishes between general application screens and
* temporary screens (like dialogs, error messages, etc.). The latter are
* expected to be displayed only for a short time and not be part of the screen
* stack. A separate stack of temporary screens is used to manage multiple
* temporary screens. As long as this stack is not empty always the topmost
* temporary screen will be displayed even if the application screen is changed
* with one of the the screen manager methods {@link #show(Displayable)}, {@link
* #previous()}, and {@link #setCurrent(Displayable)}.</p>
*
* <p><b>Attention:</b> It is important for code that displays temporary screens
* that it removes these screens correctly because otherwise the application
* could be rendered unusable by the temporary screen that is still displayed
* (as these often have no commands associated with them). It is recommended to
* use a try-finally block to ensure correct temporary screen removal through
* the {@link #showTemporary(Displayable)} method.</p>
*
* <p>This class must be used in conjunction with MIDlets that are derived from
* the J2ME-Lib {@link BasicMidlet} class because it needs to query the display
* from the {@link BasicMidlet#getDisplay()} method to be able to display
* screens.</p>
*
* @author eso
*/
public class ScreenManager
{
  //~ Static fields/initializers ---------------------------------------------

  /** Stack of the application screens (Displayable instances) */
  private static Stack aScreenStack = new Stack();

  /** Stack of temporary screens (Dialogs etc., Displayable instances) */
  private static Stack aTemporaryScreenStack = new Stack();

  //~ Constructors -----------------------------------------------------------

  /***************************************
   * The Constructor is private because access to this is done through static
   * methods - no instances of ScreenManager will ever be used.
   */
  private ScreenManager()
  {
  }

  //~ Methods ----------------------------------------------------------------

  /***************************************
   * Return the currently active application screen. Temporary screens are
   * ignored because they are only intended to be displayed for a short time.
   * That means that the returned screen (if not NULL) is not necessarily the
   * currently <b>displayed</b> screen because that may be a temporary screen
   * that is active at that time. But the currently visible screen can always
   * be queried by means of the <code>Display.getCurrent()</code> method.
   *
   * @return The currently active application screen Displayable or NULL if no
   *         screen has been set with <code>show()</code> before
   */
  public static Displayable getCurrent()
  {
    return ((aScreenStack.size() > 0) ? (Displayable) aScreenStack.peek()
                      : null);
  }

  /***************************************
   * Return the currently active temporary screen. If the returned screen is
   * not NULL it will also be the currently visible screen.
   *
   * @return The currently temporary screen Displayable or NULL if no
   *         temporary screen has been set with <code>showTemporary()</code>
   */
  public static Displayable getTemporary()
  {
    return (Displayable) aTemporaryScreenStack.peek();
  }

  /***************************************
   * To activate the previous application screen from the internal screen
   * stack. The current topmost screen will be discarded from the screen stack
   * and, if no temporary screen is currently active, the new top screen will
   * be displayed. If a temporary screen is active then the previoud
   * application screen will become visible after the last temporary screen is
   * removed by the method <code>previousTemporary()</code>.
   */
  public static void previous()
  {
    previous(aScreenStack);
  }

  /***************************************
   * To activate and display the previous screen after a temporary screen has
   * been shown. This may either be another temporary screen that has been
   * visible before or, if no more temporary screens are available, the
   * topmost application screen.
   */
  public static void previousTemporary()
  {
    previous(aTemporaryScreenStack);
  }

  /***************************************
   * This method will display the current screen depending on the state of the
   * internal stacks: if a temporary screen is available it will be shown,
   * else the topmost application screen will be displayed.
   *
   * <p>If no screen is available at all the display will not be changed but
   * <code>Display.setCurrent(null)</code> will be invoked. According to the
   * J2ME 1.0 specification this is interpreted as a hint that the application
   * may be put in the background. Therefore, an application that only
   * displays temporary screens from time to time can use the ScreenManager
   * class too.</p>
   */
  public static void refresh()
  {
    Displayable rScreen = null;

    if (aTemporaryScreenStack.size() > 0)
    {
      rScreen = (Displayable) aTemporaryScreenStack.peek();
    }
    else if (aScreenStack.size() > 0)
    {
      rScreen = (Displayable) aScreenStack.peek();
    }

    if (rScreen != null)
    {
      BasicMidlet.getDisplay().setCurrent(rScreen);
    }
  }

  /***************************************
   * To set (or: replace) the currently active application screen. If no
   * temporary screen is currently visible the new application screen will
   * become visible immediately. Otherwise it will be displayed right after no
   * temporary screen is visible anymore. This method can and should be used
   * to update the active application screen without changing the screen
   * stack. Calling previous() and show() instead would result in flicker
   * because the previous screen could become visible for a short time.
   *
   * @param rNewScreen The new screen to replace the active screen with
   */
  public static void setCurrent(Displayable rNewScreen)
  {
    if (aScreenStack.size() > 0)
    {
      aScreenStack.pop();
    }

    show(rNewScreen);
  }

  /***************************************
   * Sets and displays the next application screen. If the current screen had
   * also been set with this method it is available on the internal stack of
   * application screens and can be re-displayed later by invoking the method
   * <code>previous()</code>. If the current screen doesn't need to be saved
   * (e.g. in case of an update) the method <code>setCurrent()</code> should
   * be called instead.
   *
   * <p>If an application screen is currently active the new screen will be
   * displayed immediately (through Display.setCurrent()). If currently a
   * temporary screen is active then the display is delayed until the
   * temporary screen is removed.</p>
   *
   * @param rNextScreen The Displayable instance to display next
   */
  public static void show(Displayable rNextScreen)
  {
    show(rNextScreen, aScreenStack);
  }

  /***************************************
   * To display a temporary screen and to save it on the internal temporary
   * screen stack. If no application screen has been displayed befo
   *
   * @param rTempScreen The temporary screen to display
   */
  public static void showTemporary(Displayable rTempScreen)
  {
    show(rTempScreen, aTemporaryScreenStack);
  }

  /***************************************
   * Internal method to fetch a previous screen from a stack and to display
   * the resulting active screen (either a temporary or an application
   * screen).
   *
   * @param rStack The stack from which to fetch the screen
   */
  private static synchronized void previous(Stack rStack)
  {
    if (rStack.size() > 0)
    {
      rStack.pop();
    }
    else if (J2meLib.LOGGING)
    {
      Log.info("ScreenManager.previous(): no previous screen");
      new Exception().printStackTrace();
    }

    refresh();
  }

  /***************************************
   * Internal method to add a screen Displayable to a stack and to display the
   * resulting active screen (either a temporary or an application screen).
   *
   * @param rNextScreen The Displayable instance to add and display
   * @param rStack      The stack to add the screen to
   */
  private static synchronized void show(Displayable rNextScreen, Stack rStack)
  {
    rStack.push(rNextScreen);
    refresh();
  }
}
TOP

Related Classes of de.esoco.j2me.ui.ScreenManager

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.