org.jpos.ui.UI Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jpos Show documentation
Show all versions of jpos Show documentation
jPOS is an ISO-8583 based financial transaction
library/framework that can be customized and
extended in order to implement financial interchanges.
/*
* jPOS Project [http://jpos.org]
* Copyright (C) 2000-2020 jPOS Software SRL
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package org.jpos.ui;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jpos.util.Log;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
/**
* @author Alejandro Revilla
*
* jPOS UI main class
*
* @see UIFactory
*
* See src/examples/ui/* for usage details
*/
@SuppressWarnings({"unchecked", "deprecation"})
public class UI implements UIFactory, UIObjectFactory {
JFrame mainFrame;
Map registrar, mapping;
Element config;
UIObjectFactory objFactory;
Log log;
boolean destroyed = false;
static final ResourceBundle classMapping;
static {
classMapping = ResourceBundle.getBundle(UI.class.getName());
}
/**
* Create a new UI object
*/
public UI () {
super ();
registrar = new HashMap ();
mapping = new HashMap ();
setObjectFactory (this);
}
/**
* Creates a new UI object
* @param config configuration element
*/
public UI (Element config) {
this ();
setConfig(config);
}
/**
* Assigns an object factory use to create new object instances.
* If no object factory is asigned, UI uses the default classloader
*
* @param objFactory reference to an Object Factory
*/
public void setObjectFactory (UIObjectFactory objFactory) {
this.objFactory = objFactory;
}
/**
* @param config the Configuration element
*/
public void setConfig (Element config) {
this.config = config;
}
/**
* @param log an optional Log instance
* @see org.jpos.util.Log
*/
public void setLog (Log log) {
this.log = log;
}
public Log getLog () {
return log;
}
/**
* UI uses a map to hold references to its components
* ("id" attribute)
*
* @return UI component registrar
*/
public Map getRegistrar () {
return registrar;
}
/**
* @param id Component id ("id" configuration attribute)
* @return the Object or null
*/
public Object get (String id) {
return registrar.get (id);
}
/**
* UI is itself a UIFactory.
* This strategy is used to recursively instantiate components
* inside a container
*
* @param ui reference to this UI instance
* @param e free form configuration Element
* @return JComponent
*/
public JComponent create (UI ui, Element e) {
return create(e);
}
/**
* UIObjectFactory implementation.
* uses default classloader
* @param clazz the Clazzzz
* @return the Object
* @throws Exception if unable to instantiate
* @see #setLog
*/
public Object newInstance (String clazz) throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader ();
Class type = cl.loadClass (clazz);
return type.newInstance();
}
/**
* configure this UI object
*/
public void configure () throws JDOMException {
configure (config);
}
/**
* reconfigure can be used in order to re-configure components
* inside a container (i.e. changing a panel in response to
* an event).
* @see org.jpos.ui.action.Redirect
*
* @param elementName the element name used as new configuration
* @param panelName panel ID (see "id" attribute)
*/
public void reconfigure (String elementName, String panelName) {
Container c =
panelName == null ? mainFrame.getContentPane() : (JComponent) get (panelName);
if (c != null) {
c.removeAll ();
c.add (
createComponent (config.getChild (elementName))
);
if (c instanceof JComponent) {
c.revalidate();
}
c.repaint ();
}
}
/**
* dispose this UI object
*/
public void dispose () {
/* This is the right code for the dispose, but it freezes in
JVM running under WinXP (in linux went fine.. I didn't
test it under other OS's)
(last version tested: JRE 1.5.0-beta2)
if (mainFrame != null) {
// dumpComponent (mainFrame);
mainFrame.dispose ();
*/
destroyed = true;
Iterator it = Arrays.asList(Frame.getFrames()).iterator();
while (it.hasNext()) {
JFrame jf = (JFrame) it.next();
removeComponent(jf);
}
}
/**
* @return true if this UI object has been disposed and is no longer valid
*/
public boolean isDestroyed () {
return destroyed;
}
protected void configure (Element ui) throws JDOMException {
setLookAndFeel (ui);
createMappings (ui);
createObjects (ui, "object");
createObjects (ui, "action");
if (!"ui".equals (ui.getName())) {
ui = ui.getChild ("ui");
}
if (ui != null) {
JFrame frame = initFrame (ui);
Element mb = ui.getChild ("menubar");
if (mb != null)
frame.setJMenuBar (buildMenuBar (mb));
frame.setContentPane (
createComponent (ui.getChild ("components"))
);
if ("true".equals (ui.getAttributeValue ("full-screen"))) {
GraphicsDevice device = GraphicsEnvironment
.getLocalGraphicsEnvironment()
.getDefaultScreenDevice();
frame.setUndecorated (
"true".equals (ui.getAttributeValue ("undecorated"))
);
device.setFullScreenWindow(frame);
} else {
frame.show ();
}
}
}
private void removeComponent (Component c) {
if (c instanceof Container) {
Container cont = (Container) c;
Component[] cc = cont.getComponents();
for (Component aCc : cc) {
removeComponent(aCc);
}
cont.removeAll();
}
}
// ##DEBUG##
private void dumpComponent (Component c) {
System.out.println (c.getClass().getName() + ":" + c.getBounds().getSize().toString());
if (c instanceof Container) {
Component[] cc = ((Container) c).getComponents();
for (Component aCc : cc) {
dumpComponent(aCc);
}
}
}
private JFrame initFrame (Element ui) {
Element caption = ui.getChild ("caption");
mainFrame = caption == null ?
new JFrame () :
new JFrame (caption.getText());
JOptionPane.setRootFrame (mainFrame);
mainFrame.getContentPane().setLayout(new BorderLayout());
String close = ui.getAttributeValue ("close");
if ("false".equals (close))
mainFrame.setDefaultCloseOperation (JFrame.DO_NOTHING_ON_CLOSE);
else if ("exit".equals (close))
mainFrame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
mainFrame.setSize(getDimension (ui, screenSize));
locateOnScreen(mainFrame);
return mainFrame;
}
private void locateOnScreen(Frame frame) {
Dimension paneSize = frame.getSize();
Dimension screenSize = frame.getToolkit().getScreenSize();
frame.setLocation(
(screenSize.width - paneSize.width) / 2,
(screenSize.height - paneSize.height) / 2);
}
private JMenuBar buildMenuBar (Element ui) {
JMenuBar mb = new JMenuBar ();
Iterator iter = ui.getChildren("menu").iterator();
while (iter.hasNext())
mb.add (menu ((Element) iter.next()));
return mb;
}
private JMenu menu (Element m) {
JMenu menu = new JMenu (m.getAttributeValue ("id"));
setItemAttributes (menu, m);
Iterator iter = m.getChildren ().iterator();
while (iter.hasNext())
addMenuItem(menu, (Element) iter.next());
return menu;
}
private void addMenuItem (JMenu menu, Element m) {
String tag = m.getName ();
if ("menuitem".equals (tag)) {
JMenuItem item = new JMenuItem (m.getAttributeValue ("id"));
setItemAttributes (item, m);
menu.add (item);
} else if ("menuseparator".equals (tag)) {
menu.addSeparator ();
} else if ("button-group".equals (tag)) {
addButtonGroup (menu, m);
} else if ("check-box".equals (tag)) {
JCheckBoxMenuItem item = new JCheckBoxMenuItem (
m.getAttributeValue ("id")
);
setItemAttributes (item, m);
item.setState (
"true".equals (m.getAttributeValue ("state"))
);
menu.add (item);
} else if ("menu".equals (tag)) {
menu.add (menu (m));
}
}
private void addButtonGroup (JMenu menu, Element m) {
ButtonGroup group = new ButtonGroup();
Iterator iter = m.getChildren ("radio-button").iterator();
while (iter.hasNext()) {
addRadioButton (menu, group, (Element) iter.next());
}
}
private void addRadioButton (JMenu menu, ButtonGroup group, Element m) {
JRadioButtonMenuItem item = new JRadioButtonMenuItem
(m.getAttributeValue ("id"));
setItemAttributes (item, m);
item.setSelected (
"true".equals (m.getAttributeValue ("selected"))
);
group.add (item);
menu.add (item);
}
private Dimension getDimension (Element e, Dimension def) {
String w = e.getAttributeValue ("width");
String h = e.getAttributeValue ("height");
return new Dimension (
w != null ? Integer.parseInt (w) : def.width,
h != null ? Integer.parseInt (h) : def.height
);
}
private void setItemAttributes (AbstractButton b, Element e)
{
String s = e.getAttributeValue ("accesskey");
if (s != null && s.length() == 1)
b.setMnemonic (s.charAt(0));
String icon = e.getAttributeValue ("icon");
if (icon != null) {
try {
b.setIcon (new ImageIcon (new URL (icon)));
} catch (MalformedURLException ex) {
ex.printStackTrace ();
}
}
b.setActionCommand (e.getAttributeValue ("command"));
String actionId = e.getAttributeValue ("action");
if (actionId != null) {
b.addActionListener ((ActionListener) get (actionId));
}
}
protected void setLookAndFeel (Element ui) {
String laf = ui.getAttributeValue ("look-and-feel");
if (laf != null) {
try {
UIManager.setLookAndFeel (laf);
} catch (Exception e) {
warn (e);
}
}
}
private JComponent createComponent (Element e) {
if (e == null)
return new JPanel ();
JComponent component;
UIFactory factory = null;
String clazz = e.getAttributeValue ("class");
if (clazz == null)
clazz = (String) mapping.get (e.getName());
if (clazz == null) {
try {
clazz = classMapping.getString (e.getName());
} catch (MissingResourceException ignored) {
// OK to happen on components handled by this factory
}
}
try {
if (clazz == null)
factory = this;
else
factory = (UIFactory) objFactory.newInstance (clazz.trim());
component = factory.create (this, e);
setSize (component, e);
if (component instanceof AbstractButton) {
AbstractButton b = (AbstractButton) component;
b.setActionCommand (e.getAttributeValue ("command"));
String actionId = e.getAttributeValue ("action");
if (actionId != null) {
b.addActionListener ((ActionListener) get (actionId));
}
}
put (component, e);
Element script = e.getChild ("script");
if (script != null)
component = doScript (component, script);
if ("true".equals (e.getAttributeValue ("scrollable")))
component = new JScrollPane (component);
} catch (Exception ex) {
warn ("Error instantiating class " + clazz);
warn (ex);
component = new JLabel ("Error instantiating class " + clazz);
}
return component;
}
protected JComponent doScript (JComponent component, Element e) {
return component;
}
private void setSize (JComponent c, Element e) {
String w = e.getAttributeValue ("width");
String h = e.getAttributeValue ("height");
Dimension d = c.getPreferredSize ();
double dw = d.getWidth ();
double dh = d.getHeight ();
if (w != null)
dw = Double.parseDouble (w);
if (h != null)
dh = Double.parseDouble (h);
if (w != null || h != null) {
d.setSize (dw, dh);
c.setPreferredSize (d);
}
}
public JComponent create (Element e) {
JComponent component = null;
Iterator iter = e.getChildren().iterator();
for (int i=0; iter.hasNext(); i++) {
JComponent c = createComponent((Element) iter.next ());
if (i == 0)
component = c;
else if (i == 1) {
JPanel p = new JPanel ();
p.add (component);
p.add (c);
component = p;
put (component, e);
} else {
component.add (c);
}
}
return component;
}
public JFrame getMainFrame() {
return mainFrame;
}
private void createObjects (Element e, String name) {
Iterator iter = e.getChildren (name).iterator ();
while (iter.hasNext()) {
try {
Element ee = (Element) iter.next ();
String clazz = ee.getAttributeValue ("class");
Object obj = objFactory.newInstance (clazz.trim());
if (obj instanceof UIAware) {
((UIAware) obj).setUI (this, ee);
}
put (obj, ee);
} catch (Exception ex) {
warn (ex);
}
}
}
private void createMappings (Element e) {
Iterator iter = e.getChildren ("mapping").iterator ();
while (iter.hasNext()) {
try {
Element ee = (Element) iter.next ();
String name = ee.getAttributeValue ("name");
String clazz = ee.getAttributeValue("factory");
mapping.put(name, clazz);
} catch (Exception ex) {
warn (ex);
}
}
}
protected void warn (Object obj) {
if (log != null)
log.warn (obj);
}
protected void warn (Object obj, Exception ex) {
if (log != null)
log.warn (obj, ex);
}
private void put (Object obj, Element e) {
String id = e.getAttributeValue ("id");
if (id != null) {
registrar.put (id, obj);
}
}
}