package org.openslx.dozmod.gui.window;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.log4j.Logger;
import org.apache.thrift.TException;
import org.openslx.bwlp.thrift.iface.ImageSummaryRead;
import org.openslx.bwlp.thrift.iface.TAuthorizationException;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.dozmod.filetransfer.TransferHelper;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.MainWindow;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.gui.helper.PopupMenu;
import org.openslx.dozmod.gui.window.ImageDetailsWindow.ImageUpdatedCallback;
import org.openslx.dozmod.gui.window.layout.ImageListWindowLayout;
import org.openslx.dozmod.gui.wizard.ImageWizard;
import org.openslx.dozmod.gui.wizard.LectureWizard;
import org.openslx.dozmod.permissions.ImagePerms;
import org.openslx.dozmod.thrift.ImageCache;
import org.openslx.dozmod.thrift.Session;
import org.openslx.dozmod.thrift.UserCache;
import org.openslx.dozmod.util.FormatHelper;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.QuickTimer;
import org.openslx.util.QuickTimer.Task;
/**
* @author joe
*
*/
@SuppressWarnings("serial")
public class ImageListWindow extends ImageListWindowLayout {
private final static Logger LOGGER = Logger.getLogger(ImageListWindow.class);
public final ImageListWindow me = this;
private final JMenuItem popupItemNewLecture = new JMenuItem("Neue Veranstaltung");
private final JMenuItem popupItemDelete = new JMenuItem("Löschen");
private final JMenuItem popupItemDownload = new JMenuItem("Download");
public ImageListWindow() {
super();
// filter the objects in the table depending on the search field
searchTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void changedUpdate(DocumentEvent e) {
// stuff
applyFilterOnTable();
}
});
// Setup popup menu for the right panel
final PopupMenu pop = new PopupMenu(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(popupItemNewLecture)) {
startLectureWizard(imageTable.getSelectedItem());
}
if (e.getSource().equals(popupItemDownload)) {
performImageDownload(imageTable.getSelectedItem());
}
if (e.getSource().equals(popupItemDelete)) {
// TODO delete that image
LOGGER.debug("Delete image clicked");
}
}
});
// add them to the popup menu
pop.addMenuItem(popupItemNewLecture);
pop.addMenuItem(popupItemDownload);
pop.addSeparator();
pop.addMenuItem(popupItemDelete);
filterCbo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyFilterOnTable();
}
});
imageTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
ImageSummaryRead item = imageTable.getSelectedItem();
updateAvailableOptions(item);
}
});
imageTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
final ImageSummaryRead image = getSelectedImage();
if (image == null)
return;
ImageDetailsWindow.open((JFrame) SwingUtilities.getWindowAncestor(me),
image.getImageBaseId(), new ImageUpdatedCallback() {
public void updated() {
refreshList(true);
}
});
}
processClick(e);
}
@Override
public void mousePressed(MouseEvent e) {
processClick(e);
}
@Override
public void mouseReleased(MouseEvent e) {
processClick(e);
}
private void processClick(MouseEvent e) {
int r = imageTable.rowAtPoint(e.getPoint());
if (r >= 0 && r < imageTable.getRowCount()) {
// highlight the row and popup the menu
imageTable.setRowSelectionInterval(r, r);
if (e.isPopupTrigger()) {
pop.show(e.getComponent(), e.getX(), e.getY());
}
} else {
imageTable.clearSelection();
}
}
});
newButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new ImageWizard(SwingUtilities.getWindowAncestor(me)).setVisible(true);
refreshList(true);
}
});
downloadButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
performImageDownload(imageTable.getSelectedItem());
}
});
// delete lecture
deleteButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent ae) {
deleteLatestVersion(getSelectedImage());
}
});
newLectureButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startLectureWizard(imageTable.getSelectedItem());
}
});
// return to mainMenu
backButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MainWindow.showPage(MainMenuWindow.class);
}
});
updateAvailableOptions(null);
}
/********************************************************************************
*
* General GUI and table helpers
*
********************************************************************************/
/**
* Refreshes the image list in the table
*
* @param forceRefresh true to force a refresh, false to use the cached list
*/
private void refreshList(final boolean forceRefresh) {
QuickTimer.scheduleOnce(new Task() {
@Override
public void fire() {
final List<ImageSummaryRead> imageList = ImageCache.get(forceRefresh);
Gui.asyncExec(new Runnable() {
@Override
public void run() {
imageTable.setData(imageList, true);
}
});
}
});
}
/**
* Helper to return the selected image from the table or show an error to the user if none is selected
*
* @return the image selected in the table, null if there is no selection
*/
private final ImageSummaryRead getSelectedImage() {
final ImageSummaryRead image = imageTable.getSelectedItem();
if (image == null) {
Gui.showMessageBox(this, "Kein Image ausgewählt!", MessageType.ERROR, LOGGER, null);
return null;
} else {
return image;
}
}
/**
* Helper to check if the given image has a latest version
*
* @param image the image to check for a latest version
* @return true if the image has a latest version, false otherwise
*/
private boolean hasLatestVersion(ImageSummaryRead image) {
if (image == null)
return false;
if (image.getLatestVersionId() == null) {
Gui.showMessageBox(me, "Das gewählte Image besitzt keine gültige Image-Version",
MessageType.ERROR, null, null);
return false;
}
return true;
}
/**
* Filters the image list according to the filter text entered by the user
*/
private void applyFilterOnTable() {
try {
// List for filters
List<RowFilter<Object, Object>> filters = new ArrayList<RowFilter<Object, Object>>(3);
// string for text in filter text field
String filterField = searchTextField.getText();
filters.add(RowFilter.regexFilter("(?i)" + filterField, 0, 1, 2));
// filter for user (only show own)
switch (filterCbo.getSelectedIndex()) {
case 0:
// no additional filters
break;
case 1:
// filter for owner
String userFilter = FormatHelper.userName(UserCache.find(Session.getUserId()));
filters.add(RowFilter.regexFilter("(?i)" + userFilter, 2));
break;
case 2:
// filter for editable
RowFilter<Object, Object> filter = new RowFilter<Object, Object>() {
public boolean include(Entry entry) {
return ImagePerms.canEdit(imageTable.getModelRow((Integer) entry.getIdentifier()));
}
};
filters.add(filter);
break;
case 3:
// show only templates
RowFilter<Object, Object> templateFilter = new RowFilter<Object, Object>() {
public boolean include(Entry entry) {
return imageTable.getModelRow((Integer) entry.getIdentifier()).isTemplate;
}
};
filters.add(templateFilter);
default:
break;
}
// for using multiple filters
RowFilter<Object, Object> andFilters = RowFilter.andFilter(filters);
imageTable.getRowSorter().setRowFilter(andFilters);
searchTextField.setForeground(UIManager.getColor("TextField.foreground"));
} catch (IllegalArgumentException ex) {
// TODO set background color of search field to something redish
searchTextField.setForeground(Color.RED);
}
}
/**
* Updates the buttons/popup menu items according to the user's permissions
*
* @param item the image to check the user's permissions for
*/
private void updateAvailableOptions(ImageSummaryRead item) {
boolean download = ImagePerms.canDownload(item);
boolean link = ImagePerms.canLink(item);
boolean admin = ImagePerms.canAdmin(item);
downloadButton.setEnabled(download);
newLectureButton.setEnabled(link);
deleteButton.setEnabled(admin);
popupItemDownload.setEnabled(download);
popupItemNewLecture.setEnabled(link);
popupItemDelete.setEnabled(admin);
}
/********************************************************************************
*
* Helpers triggering the remote thrift calls
*
********************************************************************************/
/**
* Starts a lecture wizard for the given image if it has a valid version
*
* @param image image to link the new lecture to
*/
private void startLectureWizard(ImageSummaryRead image) {
if (!hasLatestVersion(image))
return;
new LectureWizard(SwingUtilities.getWindowAncestor(this), image, image.getLatestVersionId()).setVisible(true);
}
/**
* Triggers a download of the given image's latest version
*
* @param image the image to download
*/
private void performImageDownload(ImageSummaryRead image) {
if (!hasLatestVersion(image))
return;
downloadButton.setEnabled(false);
TransferHelper.initDownload(JOptionPane.getFrameForComponent(this), image.latestVersionId,
image.imageName, image.virtId, image.fileSize);
}
/**
* Deletes the latest version of the given image if it has one
*
* @param image image to delete
*/
private void deleteLatestVersion(final ImageSummaryRead image) {
if (!hasLatestVersion(image))
return;
// requires confirmation of the user
if (!Gui.showMessageBox(me, "Wollen Sie die letzte Version von dieses Image wirklich löschen?", MessageType.QUESTION_YESNO, LOGGER, null))
return;
// try to actually delete this version of the image
try {
ThriftManager.getSatClient().deleteImageVersion(Session.getSatelliteToken(),
image.getLatestVersionId());
LOGGER.info("Deleted version '" + image.getLatestVersionId() + "' of image '"
+ image.getImageBaseId() + "'.");
refreshList(true);
} catch (TAuthorizationException e) {
Gui.showMessageBox(me, "Sie sind nicht autorisiert dieses Image zu löschen!",
MessageType.ERROR, LOGGER, e);
} catch (TNotFoundException e) {
Gui.showMessageBox(me, "Diese Image existiert nicht auf dem Satelliten!",
MessageType.ERROR, LOGGER, e);
} catch (TException e) {
Gui.showMessageBox(me, "Interner Fehler! Siehe Logs.", MessageType.ERROR, LOGGER, e);
}
}
/********************************************************************************
*
* CompositePage abstract methods implementation
*
********************************************************************************/
@Override
public boolean requestHide() {
return true;
}
@Override
public void requestShow() {
refreshList(false);
}
}