/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
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 http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.smart;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import com.servoy.j2db.FormController;
import com.servoy.j2db.FormManager;
import com.servoy.j2db.ISmartClientApplication;
import com.servoy.j2db.Messages;
import com.servoy.j2db.gui.FixedJList;
import com.servoy.j2db.persistence.Form;
import com.servoy.j2db.smart.cmd.MenuWindowAction;
import com.servoy.j2db.util.Settings;
import com.servoy.j2db.util.gui.JEscapeDialog;
import com.servoy.j2db.util.gui.JMenuAlwaysEnabled;
import com.servoy.j2db.util.gui.SortedListModel;
/**
* The dialog which shows the list of forms
*
* @author jcompagner
*/
public class WindowMenuDialog implements ActionListener
{
public static final int MAX_ITEMS = 20;
private WindowDialog windowsDialog;
private JMenuItem moreWindowsMenuItem;
private JMenu windowMenu;
private ButtonGroup group;
protected HashMap formMenuItems; // formName -> JMenuItem
protected SwingFormManager actionListener;
protected ArrayList inMenu;
private final ISmartClientApplication application;
public WindowMenuDialog(ISmartClientApplication application, SwingFormManager actionListener)
{
super();
this.application = application;
this.actionListener = actionListener;
formMenuItems = new HashMap();
inMenu = new ArrayList();
}
public JMenu getWindowMenu()
{
if (windowMenu == null)
{
group = new ButtonGroup();
windowMenu = new JMenuAlwaysEnabled(new MenuWindowAction(application));
windowMenu.setEnabled(false);
}
return windowMenu;
}
protected JRadioButtonMenuItem addForm(Form form)
{
if (windowMenu == null)
{
// headless client? addForm to menu doesn't make any sense for a headless client
return null;
}
JRadioButtonMenuItem mi = (JRadioButtonMenuItem)formMenuItems.get(form.getUUID());
if (mi != null) return mi;
if (form.getShowInMenu() || actionListener.getShowFormsAllInWindowMenu())
{
if (windowMenu.getMenuComponentCount() > MAX_ITEMS)
{
removeOldest();
if (moreWindowsMenuItem == null)
{
removeOldest();
moreWindowsMenuItem = new JMenuItem(Messages.getString("servoy.windowMenuDialog.more")); //$NON-NLS-1$
moreWindowsMenuItem.addActionListener(this);
windowMenu.insertSeparator(0);
windowMenu.insert(moreWindowsMenuItem, 0);
if ("true".equals(application.getSettings().getProperty("windowdialog_state", "false"))) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
{
if (windowsDialog == null)
{
windowsDialog = new WindowDialog();
}
windowsDialog.showDialog();
}
}
}
mi = new JRadioButtonMenuItem(form.getName());
if (form.getShowInMenu() && actionListener.getShowFormsAllInWindowMenu())
{
mi.setIcon(application.loadImage("showinmenuform.gif")); //$NON-NLS-1$
}
else
{
mi.setIcon(application.loadImage("empty.gif")); //$NON-NLS-1$
}
mi.addActionListener(actionListener);
formMenuItems.put(form.getUUID(), mi);
insertMenuItem(form, mi);
if (windowsDialog != null)
{
windowsDialog.listModel.add(mi);
}
group.add(mi);
return mi;
}
return null;
}
private void insertMenuItem(Form form, JRadioButtonMenuItem mi)
{
mi.updateUI(); // make sure that font or other l&f settings are applied.
int count = windowMenu.getMenuComponentCount();
if (count == 0)
{
inMenu.add(mi);
windowMenu.setEnabled(true);
windowMenu.add(mi);
}
else
{
int i = 0;
if (windowMenu.getMenuComponent(0) == moreWindowsMenuItem)
{
i = 2;
}
for (; i < count; i++)
{
Component comp = windowMenu.getMenuComponent(i);
if (comp instanceof JMenuItem)
{
JMenuItem item = (JMenuItem)comp;
if (item.getText().compareToIgnoreCase(form.getName()) > 0)
{
break;
}
}
else
{
break;
}
}
inMenu.add(mi);
windowMenu.insert(mi, i);
}
}
private void removeOldest()
{
JRadioButtonMenuItem item = (JRadioButtonMenuItem)inMenu.remove(0);
while (item.isSelected())
{
inMenu.add(item);
item = (JRadioButtonMenuItem)inMenu.remove(0);
}
windowMenu.remove(item);
}
public void destroy()
{
if (windowMenu != null)
{
windowMenu.removeAll();
windowMenu.setEnabled(false);
}
formMenuItems = new HashMap();
group = new ButtonGroup();
inMenu = new ArrayList();
if (windowsDialog != null)
{
windowsDialog.dispose();
windowsDialog = null;
}
moreWindowsMenuItem = null;
}
/**
* @param f
*/
public void selectForm(Form f)
{
JRadioButtonMenuItem mi = (JRadioButtonMenuItem)formMenuItems.get(f.getUUID());
if (mi == null) return;
if (mi.getParent() == null)
{
removeOldest();
insertMenuItem(f, mi);
}
else
{
if (inMenu.remove(mi))
{
inMenu.add(mi);
}
}
if (mi != null && !mi.isSelected()) mi.setSelected(true);
}
/**
* @param form
*/
public void formChanged(final Form form)
{
final JMenuItem mi = (JMenuItem)formMenuItems.get(form.getUUID());
if (mi != null)
{
application.invokeLater(new Runnable()
{
public void run()
{
String name = form.getName();
if (windowsDialog != null)
{
windowsDialog.listModel.remove(mi);
}
mi.setText(name);
mi.setActionCommand(name);
if (form.getShowInMenu() && actionListener.getShowFormsAllInWindowMenu())
{
mi.setIcon(application.loadImage("showinmenuform.gif")); //$NON-NLS-1$
}
else
{
mi.setIcon(application.loadImage("empty.gif")); //$NON-NLS-1$
}
if (windowsDialog != null)
{
windowsDialog.listModel.add(mi);
}
}
});
}
}
/**
* @param form
*/
public void removeForm(Form form)
{
JMenuItem menuItem = (JMenuItem)formMenuItems.get(form.getUUID());
formMenuItems.remove(form.getUUID());
if (menuItem != null)
{
Container m = menuItem.getParent();
if (m != null)
{
m.remove(menuItem);
}
if (windowsDialog != null)
{
windowsDialog.listModel.remove(menuItem);
}
}
}
/**
* @param form
*/
public void refreshFrom(Form form)
{
JMenuItem menuItem = (JMenuItem)formMenuItems.get(form.getUUID());
if (menuItem != null)
{
menuItem.setText(form.getName());
if (form.getShowInMenu() && actionListener.getShowFormsAllInWindowMenu())
{
menuItem.setIcon(application.loadImage("showinmenuform.gif")); //$NON-NLS-1$
}
else
{
menuItem.setIcon(application.loadImage("empty.gif")); //$NON-NLS-1$
}
}
}
/**
*
*/
public void clearList()
{
if (windowsDialog != null)
{
windowsDialog.listModel.removeAll();
}
}
public void actionPerformed(ActionEvent e)
{
if (e.getSource() == moreWindowsMenuItem)
{
if (windowsDialog == null)
{
windowsDialog = new WindowDialog();
}
windowsDialog.showDialog();
}
}
private class WindowDialog extends JEscapeDialog implements KeyListener, MouseListener
{
protected FixedJList list;
protected SortedListModel listModel;
public WindowDialog()
{
super(application.getMainApplicationFrame(), Messages.getString("servoy.windowMenuDialog.chooseForm"), false); //$NON-NLS-1$
setName("windowdialog"); //$NON-NLS-1$
getContentPane().setLayout(new BorderLayout());
listModel = new SortedListModel(new MenuItemComparator(), formMenuItems.values());
list = new FixedJList();
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(this);
list.addKeyListener(this);
list.setCellStringValue(new MenuItemCellString());
list.setCellRenderer(new MenuItemRenderer());
list.setModel(listModel);
getContentPane().add(new JScrollPane(list), BorderLayout.CENTER);
if (!Settings.getInstance().loadBounds(this))
{
this.setLocationRelativeTo(application.getMainApplicationFrame());
this.setSize(new Dimension(200, 300));
}
application.registerWindow("windowdialog", this); //$NON-NLS-1$
}
public void showDialog()
{
FormController fc = ((FormManager)application.getFormManager()).getCurrentMainShowingFormController();
JMenuItem menuItem = (JMenuItem)formMenuItems.get(fc.getForm().getUUID());
if (menuItem != null) list.setSelectedValue(menuItem, true);
setVisible(true);
}
private void openForm()
{
JMenuItem item = (JMenuItem)list.getSelectedValue();
actionListener.actionPerformed(new ActionEvent(item, ActionEvent.ACTION_PERFORMED, item.getActionCommand()));
//setVisible(false);
}
@Override
protected void cancel()
{
setVisible(false);
}
/*
* @see java.awt.Dialog#dispose()
*/
@Override
public void dispose()
{
if (isVisible())
{
setVisible(false);
application.getSettings().setProperty("windowdialog_state", "true"); //$NON-NLS-1$//$NON-NLS-2$
}
else
{
application.getSettings().setProperty("windowdialog_state", "false"); //$NON-NLS-1$//$NON-NLS-2$
}
super.dispose();
}
/*
* (non-Javadoc)
*
* @see com.servoy.j2db.util.JEscapeDialog#setVisible(boolean)
*/
@Override
public void setVisible(boolean b)
{
if (!b)
{
Settings.getInstance().saveBounds(this);
}
super.setVisible(b);
}
public void keyTyped(KeyEvent e)
{
}
public void keyPressed(KeyEvent e)
{
}
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
{
openForm();
}
}
public void mouseReleased(MouseEvent e)
{
if (e.getClickCount() == 2)
{
openForm();
}
}
public void mouseClicked(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
private static class MenuItemRenderer extends DefaultListCellRenderer
{
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
Icon icon = null;
if (value != null && value instanceof JMenuItem)
{
icon = ((JMenuItem)value).getIcon();
value = ((JMenuItem)value).getText();
}
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (comp instanceof JLabel)
{
((JLabel)comp).setIcon(icon);
}
return comp;
}
}
private static class MenuItemComparator implements Comparator
{
public int compare(Object o1, Object o2)
{
return ((JMenuItem)o1).getText().compareToIgnoreCase(((JMenuItem)o2).getText());
}
}
private static class MenuItemCellString implements FixedJList.CellStringValue
{
public String getValue(Object value)
{
if (value != null && value instanceof JMenuItem) return ((JMenuItem)value).getText();
else if (value != null) return value.toString();
return ""; //$NON-NLS-1$
}
}
}