![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.cuf.fw2.AbstractSwingAppPc Maven / Gradle / Ivy
The newest version!
package net.sf.cuf.fw2;
import net.sf.cuf.appevent.AppEvent;
import net.sf.cuf.appevent.AppEventSupport;
import net.sf.cuf.appevent.AppEventUtil;
import net.sf.cuf.appevent.BindEvent;
import net.sf.cuf.fw.Dc;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JToolBar;
import java.awt.Component;
import java.awt.Cursor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* The AbstractSwingAppPc implements the common stuff of the AppPc interface.
* The abstract implementation supports the handling of
*
* - a menu bar,
*
- a button bar,
*
- a status line and
*
- the blocking/unblocking of the UI
*
* via the
*
* - MenuToolBarEvent,
*
- BlockEvent and
*
- ShowStatusEvent
*
* AppEvent's.
* A project specific AppPc is usually derived from AbstractSwingAppPc and
* must only (optionally) set the mMenuBar, mToolBar and mStatusLabel
* members in its init() method.
*/
public abstract class AbstractSwingAppPc implements AppPc
{
/** The separator of menu names */
public static final String SEPARATOR = "/";
/** The next object in the AppEvent responder chain. */
protected AppEventSupport mAppEventSupport;
/** Null or the toolbar we manage (must be set by the derived class). */
protected JToolBar mToolBar;
/** Null or the menubar we manage (must be set by the derived class). */
protected JMenuBar mMenuBar;
/** Maps between a menu name (this is the component name, not the displayed text!)
* and the actual menu.
* key: hierarchical menu name as String, value: MenuElement object */
protected Map mMenuMap= new HashMap<>();
/** Null or the JFrame/JDialog container to manage for block/unblock events
* (must be set by the derived class). */
protected Object mFrameOrDialog;
// helper for the block/unblock stuff
private GlassPane mGlassPane= new GlassPane();
// null or the last focused component before blocking
private Component mLastFocusOwner;
/** Null or the label we use for status text events
* (must be set by the derived class). */
protected JLabel mStatusLabel;
/**
* This method is called by the dialog controller peer during
* the initialisation phase of an application.
*
* @param pDc our peer dialog controller, must implement AppEventSupport
* @param pArgs variable argument list modeled as a key/value map,
* never null.
*/
public void init(final Dc pDc, final Map pArgs)
{
mAppEventSupport= (AppEventSupport)pDc;
// register ourselfs for changes in the menu/toolbar structure
BindEvent bindMenuToolBar= new BindEvent<>(this, this::menuToolbarChanged,
MenuToolBarEvent.class);
postAppEvent(bindMenuToolBar );
// register ourselfs for handling gui blocking/unblocking
BindEvent bindBlock = new BindEvent<>(this, this::blockChanged, BlockEvent.class);
postAppEvent(bindBlock);
// register ourselfs for status text handling
BindEvent bindShowStatus= new BindEvent<>(this, this::statusChanged, ShowStatusEvent.class);
postAppEvent(bindShowStatus);
}
/**
* Process/Dispatch an AppEvent.
*
* @param pAppEvent event that should be routed/processes
* @throws IllegalArgumentException if pAppEvent is null
*/
public void postAppEvent(AppEvent pAppEvent)
{
AppEventUtil.postAppEvent(mAppEventSupport, pAppEvent);
}
/**
* Handling of the MenuToolBarEvent. We assume that the derived class
* has initialized mToolBar, mMenuBar and mMenuMap.
* @param pEvent the event with added/removed toolbar/menu entries
*/
public void menuToolbarChanged(MenuToolBarEvent pEvent)
{
boolean delete= pEvent.isDelete();
/*
* toolbar stuff
*/
if (mToolBar!=null)
{
List toolBarButtons= pEvent.getToolBarButtons();
for (Component component : toolBarButtons)
{
if (delete)
{
mToolBar.remove(component);
}
else
{
mToolBar.add(component);
}
mToolBar.repaint();
}
}
else
{
if (pEvent.getToolBarButtons().size()>0)
{
System.err.println("derived class forgot to set our tool bar");
}
}
/*
* menu stuff
*/
if (mMenuBar!=null)
{
Map insertionMap = pEvent.getMenuInsertionIndeces();
// loop over all menus to be added/removed
for (Map.Entry entry : pEvent.getMenus().entrySet())
{
String fullParentMenuName = entry.getKey();
Object value = entry.getValue();
// check value
if (!((value instanceof List) || (value instanceof JMenuItem)))
{
throw new IllegalArgumentException("menuItem value is not a List/JMenuItem but "
+ value + ", the key was " + fullParentMenuName);
}
if (!fullParentMenuName.startsWith(SEPARATOR))
{
throw new IllegalArgumentException("menuItem name must start with a "
+ SEPARATOR);
}
// if we have just on entry, make a list out of it to simplify the code below
List menuItems;
if (value instanceof JMenuItem)
{
menuItems = new ArrayList<>(1);
menuItems.add((JMenuItem) value);
}
else
{
menuItems = (List) value;
}
// iterate over all items to be added/removed
for (final JMenuItem menuItem : menuItems)
{
// search our parent menuItem
if (!mMenuMap.containsKey(fullParentMenuName) &&
!fullParentMenuName.equals(SEPARATOR))
{
throw new IllegalArgumentException(
"could not add/delete menuItem for parent " + fullParentMenuName);
}
// update our menuItem map if we add a named menu
if ((menuItem instanceof JMenu) && (menuItem.getName() != null))
{
String menuName;
if (fullParentMenuName.endsWith(SEPARATOR))
{
menuName = fullParentMenuName + menuItem.getName();
}
else
{
menuName = fullParentMenuName + SEPARATOR + menuItem.getName();
}
if (delete)
{
mMenuMap.remove(menuName);
}
else
{
if (mMenuMap.containsKey(menuName))
{
// the menu to add is already known - we ignore the add request.
// At some later point in time we could try an intelligent merge between
// the existing and the new menu, but that is fairly complicated.
continue;
}
else
{
mMenuMap.put(menuName, menuItem);
}
}
}
// special handling for top-level menus
if (fullParentMenuName.equals(SEPARATOR))
{
if (delete)
{
mMenuBar.remove(menuItem);
}
else
{
int index = 0;
if (insertionMap.containsKey(fullParentMenuName))
{
index = insertionMap.get(fullParentMenuName);
}
if (index > 0)
{
// adjust the logical to the real index
index--;
mMenuBar.add(menuItem, index);
}
else if (index < 0)
{
// adjust the logical to the real index
index = mMenuBar.getComponentCount() + index + 1;
mMenuBar.add(menuItem, index);
}
else
{
mMenuBar.add(menuItem);
}
}
mMenuBar.repaint();
}
else
{
// handle normal menus
JMenu parentMenu = (JMenu) mMenuMap.get(fullParentMenuName);
if (delete)
{
parentMenu.remove(menuItem);
}
else
{
int index = 0;
if (insertionMap.containsKey(fullParentMenuName))
{
index = insertionMap.get(fullParentMenuName);
}
if (index > 0)
{
// adjust the logical to the real index
index--;
parentMenu.add(menuItem, index);
}
else if (index < 0)
{
// adjust the logical to the real index
index = parentMenu.getItemCount() + index + 1;
parentMenu.add(menuItem, index);
}
else
{
parentMenu.add(menuItem);
}
}
}
}
}
}
else
{
if (pEvent.getMenus().size()>0)
{
System.err.println("derived class forgot to set our menu bar");
}
}
}
/**
* Handling of BlockEvent's. We assume that the derived class
* has initialized mFrame, otherwise we do nothing.
* @param pEvent the event with the block information
*/
public void blockChanged(BlockEvent pEvent)
{
// check if we can do something at all
JFrame frame = null;
JDialog dialog= null;
if (mFrameOrDialog instanceof JFrame)
{
frame=(JFrame)mFrameOrDialog;
}
else if (mFrameOrDialog instanceof JDialog)
{
dialog=(JDialog)mFrameOrDialog;
}
if ((frame==null) && (dialog==null))
{
System.err.println("derived class forgot to set our frame/dialog");
return;
}
if ((frame!=null) && (frame.getGlassPane()!=mGlassPane))
{
frame.setGlassPane(mGlassPane);
}
if ((dialog!=null) && (dialog.getGlassPane()!=mGlassPane))
{
dialog.setGlassPane(mGlassPane);
}
if (pEvent.isBlock())
{
mGlassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
mGlassPane.setVisible(true);
mLastFocusOwner= (frame!=null) ? frame.getFocusOwner() : dialog.getFocusOwner();
mGlassPane.requestFocus();
}
else
{
mGlassPane.setCursor(Cursor.getDefaultCursor());
mGlassPane.setVisible(false);
if (mLastFocusOwner != null && pEvent.isReFocus())
{
if (mLastFocusOwner instanceof JComponent)
{
if (((JComponent)mLastFocusOwner).isRequestFocusEnabled())
{
mLastFocusOwner.requestFocus();
}
}
else
{
if (mLastFocusOwner.isEnabled())
{
mLastFocusOwner.requestFocus();
}
}
}
}
}
/**
* Handling of ShowStatusEvent 's. We assume that the derived class
* has initialized mStatusLabel, otherwise we do nothing.
* @param pEvent the event with the status text information
*/
public void statusChanged(ShowStatusEvent pEvent)
{
if (mStatusLabel!=null)
{
mStatusLabel.setText(pEvent.getStatusText());
}
else
{
System.err.println("derived class forgot to set our status label");
}
}
/**
* Called from the AppDc peer to cleanup all resources.
* The base implementation does nothing.
* @param pArgs arguments, key is a String,
* value is any suitable objekt for the key
*/
public void dispose(final Map pArgs)
{
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy