/*
* Jajuk
* Copyright (C) The Jajuk Team
* http://jajuk.info
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package org.jajuk.ui.views;
import ext.FlowScrollPanel;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.ScrollPaneConstants;
import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import org.jajuk.base.Device;
import org.jajuk.base.DeviceManager;
import org.jajuk.events.JajukEvent;
import org.jajuk.events.JajukEvents;
import org.jajuk.events.ObservationManager;
import org.jajuk.ui.helpers.JajukMouseAdapter;
import org.jajuk.ui.wizard.DeviceWizard;
import org.jajuk.util.Const;
import org.jajuk.util.IconLoader;
import org.jajuk.util.JajukIcons;
import org.jajuk.util.Messages;
import org.jajuk.util.UtilGUI;
import org.jajuk.util.error.JajukException;
/**
* Device view used to create and modify Jajuk devices
* <p>
* Configuration perspective.
*/
public class DeviceView extends ViewAdapter implements ActionListener {
/** Generated serialVersionUID. */
private static final long serialVersionUID = 1L;
/** self instance. */
private static DeviceView dv = new DeviceView();
FlowScrollPanel jpDevices;
JPopupMenu jpmenu;
JMenuItem jmiDelete;
JMenuItem jmiProperties;
JMenuItem jmiMount;
JMenuItem jmiUnmount;
JMenuItem jmiTest;
JMenuItem jmiRefresh;
JMenuItem jmiSynchronize;
DeviceItem diSelected;
/** Mouse adapter used over device items to manage action or popup clicks. */
MouseAdapter ma = new JajukMouseAdapter() {
@Override
public void handleActionSingleClick(final MouseEvent e) {
selectItem(e);
diSelected.setBorder(BorderFactory.createLineBorder(UtilGUI.getForegroundColor(), 5));
// one device already selected + right click
DeviceWizard dw = new DeviceWizard();
dw.updateWidgets(diSelected.getDevice());
dw.pack();
dw.setVisible(true);
}
@Override
public void handlePopup(final MouseEvent e) {
selectItem(e);
// a new device is selected
diSelected.setBorder(BorderFactory.createLineBorder(UtilGUI.getForegroundColor(), 5));
jpmenu.show(e.getComponent(), e.getX(), e.getY());
}
};
/**
* Instantiates a new device view.
*/
public DeviceView() {
super();
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.IView#display()
*/
@Override
public void initUI() {
// devices
jpDevices = new FlowScrollPanel();
JScrollPane jsp = new JScrollPane(jpDevices, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
jsp.setBorder(BorderFactory.createEmptyBorder(0, 1, 0, 0));
jpDevices.setScroller(jsp);
jpDevices.setLayout(new FlowLayout(FlowLayout.LEFT));
// Popup menus
jpmenu = new JPopupMenu();
jmiMount = new JMenuItem(Messages.getString("DeviceView.8"),
IconLoader.getIcon(JajukIcons.MOUNT));
jmiMount.addActionListener(this);
jmiMount.setActionCommand(JajukEvents.DEVICE_MOUNT.toString());
jpmenu.add(jmiMount);
jmiUnmount = new JMenuItem(Messages.getString("DeviceView.9"),
IconLoader.getIcon(JajukIcons.UNMOUNT));
jmiUnmount.addActionListener(this);
jmiUnmount.setActionCommand(JajukEvents.DEVICE_UNMOUNT.toString());
jpmenu.add(jmiUnmount);
jmiRefresh = new JMenuItem(Messages.getString("DeviceView.11"),
IconLoader.getIcon(JajukIcons.REFRESH));
jmiRefresh.addActionListener(this);
jmiRefresh.setActionCommand(JajukEvents.DEVICE_REFRESH.toString());
jpmenu.add(jmiRefresh);
jmiTest = new JMenuItem(Messages.getString("DeviceView.10"),
IconLoader.getIcon(JajukIcons.TEST));
jmiTest.addActionListener(this);
jmiTest.setActionCommand(JajukEvents.DEVICE_TEST.toString());
jpmenu.add(jmiTest);
jmiSynchronize = new JMenuItem(Messages.getString("DeviceView.12"),
IconLoader.getIcon(JajukIcons.SYNCHRO));
jmiSynchronize.addActionListener(this);
jmiSynchronize.setActionCommand(JajukEvents.DEVICE_SYNCHRO.toString());
jpmenu.add(jmiSynchronize);
jmiDelete = new JMenuItem(Messages.getString("DeviceView.13"),
IconLoader.getIcon(JajukIcons.DELETE));
jmiDelete.addActionListener(this);
jmiDelete.setActionCommand(JajukEvents.DEVICE_DELETE.toString());
jpmenu.add(jmiDelete);
jmiProperties = new JMenuItem(Messages.getString("DeviceView.14"),
IconLoader.getIcon(JajukIcons.CONFIGURATION));
jmiProperties.addActionListener(this);
jmiProperties.setActionCommand(JajukEvents.DEVICE_PROPERTIES.toString());
jpmenu.add(jmiProperties);
// add devices
refreshDevices();
// add components
setLayout(new MigLayout("ins 0", "[grow]", "[grow]"));
add(jsp, "grow");
// Register on the list for subject we are interested in
ObservationManager.register(this);
}
/*
* (non-Javadoc)
*
* @see org.jajuk.events.Observer#getRegistrationKeys()
*/
@Override
public Set<JajukEvents> getRegistrationKeys() {
Set<JajukEvents> eventSubjectSet = new HashSet<JajukEvents>();
eventSubjectSet.add(JajukEvents.DEVICE_MOUNT);
eventSubjectSet.add(JajukEvents.DEVICE_UNMOUNT);
eventSubjectSet.add(JajukEvents.DEVICE_NEW);
eventSubjectSet.add(JajukEvents.DEVICE_REFRESH);
return eventSubjectSet;
}
/**
* Refresh devices.
*/
private void refreshDevices() {
// remove all devices
if (jpDevices.getComponentCount() > 0) {
jpDevices.removeAll();
}
// New device
DeviceItem diNew = new DeviceItem(IconLoader.getIcon(JajukIcons.DEVICE_NEW),
Messages.getString("DeviceView.17"), null);
diNew.setToolTipText(Messages.getString("DeviceView.18"));
jpDevices.add(diNew);
diNew.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
DeviceWizard dw = new DeviceWizard();
dw.updateWidgetsDefault();
dw.pack();
dw.setVisible(true);
}
});
// Add devices
List<Device> devices = DeviceManager.getInstance().getDevices();
for (Device device : devices) {
ImageIcon icon = device.getIconRepresentationLarge();
String sTooltip = device.getHumanValue(XML_TYPE);
DeviceItem di = new DeviceItem(icon, device.getName(), device);
di.setToolTipText(sTooltip);
di.addMouseListener(ma);
di.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent e) {
super.keyTyped(e);
if (e.getKeyChar() == KeyEvent.VK_DELETE) {
handleDelete();
}
}
});
jpDevices.add(di);
}
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.views.IView#setVisible(boolean)
*/
@Override
public void setVisible(boolean pVisible) {
// don't do anything here
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.views.IView#getComponent()
*/
@Override
public Component getComponent() {
return this;
}
/**
* Singleton implementation.
*
* @return the instance
*/
public static DeviceView getInstance() {
return dv;
}
/*
* (non-Javadoc)
*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(final ActionEvent ae) {
if (ae.getActionCommand().equals(JajukEvents.DEVICE_NEW.toString())) {
DeviceWizard dw = new DeviceWizard();
dw.updateWidgetsDefault();
dw.pack();
dw.setVisible(true);
return;
}
if (diSelected == null) { // test a device is selected
return;
}
if (ae.getActionCommand().equals(JajukEvents.DEVICE_DELETE.toString())) {
handleDelete();
} else if (ae.getActionCommand().equals(JajukEvents.DEVICE_MOUNT.toString())) {
try {
diSelected.getDevice().mount(true);
} catch (JajukException je) {
Messages.showErrorMessage(je.getCode());
} catch (Exception e) {
Messages.showErrorMessage(11);
}
} else if (ae.getActionCommand().equals(JajukEvents.DEVICE_UNMOUNT.toString())) {
try {
diSelected.getDevice().unmount();
} catch (Exception e) {
Messages.showErrorMessage(12);
}
} else if (ae.getActionCommand().equals(JajukEvents.DEVICE_PROPERTIES.toString())) {
DeviceWizard dw = new DeviceWizard();
dw.updateWidgets(diSelected.getDevice());
dw.pack();
dw.setVisible(true);
} else if (ae.getActionCommand().equals(JajukEvents.DEVICE_REFRESH.toString())) {
diSelected.getDevice().refresh(true, true, false, null); // ask deep or fast
// scan
} else if (ae.getActionCommand().equals(JajukEvents.DEVICE_SYNCHRO.toString())) {
diSelected.getDevice().synchronize(true);
} else if (ae.getActionCommand().equals(JajukEvents.DEVICE_TEST.toString())) {
// Test asynchronously in case of delay (samba issue for ie)
new Thread("Asynchronous device test thread") {
@Override
public void run() {
if (diSelected.getDevice().test()) {
Messages.showInfoMessage(Messages.getString("DeviceView.21"),
IconLoader.getIcon(JajukIcons.OK));
} else {
Messages.showInfoMessage(Messages.getString("DeviceView.22"),
IconLoader.getIcon(JajukIcons.KO));
}
}
}.start();
}
}
/**
* Device deleting.
*/
void handleDelete() {
DeviceManager.getInstance().removeDevice(diSelected.getDevice());
jpDevices.remove(diSelected);
// refresh views
ObservationManager.notify(new JajukEvent(JajukEvents.DEVICE_REFRESH));
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.IView#getDesc()
*/
@Override
public String getDesc() {
return Messages.getString("DeviceView.23");
}
/*
* (non-Javadoc)
*
* @see org.jajuk.ui.Observer#update(java.lang.String)
*/
@Override
public void update(JajukEvent event) {
JajukEvents subject = event.getSubject();
if (JajukEvents.DEVICE_MOUNT.equals(subject) || JajukEvents.DEVICE_UNMOUNT.equals(subject)
|| JajukEvents.DEVICE_REFRESH.equals(subject)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
UtilGUI.waiting();
refreshDevices();
jpDevices.revalidate();
jpDevices.repaint();
UtilGUI.stopWaiting();
}
});
}
}
/**
* Select item.
*
* @param e
*/
private void selectItem(final MouseEvent e) {
boolean bSameDevice = ((diSelected != null) && e.getSource().equals(diSelected));
// remove old device item border if needed
if (!bSameDevice && diSelected != null) {
diSelected.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
}
diSelected = (DeviceItem) e.getSource();
diSelected.requestFocusInWindow();
// Test if it is the "NEW" device
if (((DeviceItem) e.getSource()).getDevice() == null) {
return;
}
// remove options for non synchronized devices
if (diSelected.getDevice().containsProperty(Const.XML_DEVICE_SYNCHRO_SOURCE)) {
jmiSynchronize.setEnabled(true);
} else {
jmiSynchronize.setEnabled(false);
}
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
/**
* Mouse exited.
*
*
* @param arg0
*/
public void mouseExited(MouseEvent arg0) {
// required by interface, but nothing to do here...
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
/**
* Mouse entered.
*
*
* @param e
*/
public void mouseEntered(MouseEvent e) {
// required by interface, but nothing to do here...
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
/**
* Mouse clicked.
*
*
* @param e
*/
public void mouseClicked(MouseEvent e) {
// required by interface, but nothing to do here...
}
}
/**
* A device icon + text Type description
*/
class DeviceItem extends JPanel {
private static final long serialVersionUID = 1L;
/** Associated device */
private Device device;
/**
* Constructor
*/
DeviceItem(ImageIcon icon, String sName, Device device) {
this.device = device;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JLabel jlIcon = new JLabel(icon);
// Add some insets around the icon
jlIcon.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
add(jlIcon);
JLabel jlName = new JLabel(sName);
jlName.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
add(jlName);
}
/**
* @return Returns the device.
*/
public Device getDevice() {
return device;
}
/**
* @param device
* The device to set.
*/
public void setDevice(Device device) {
this.device = device;
}
}