/*
* File : LibraryManager.java
* Created : 04-jun-2002 11:13
* By : fbusquets
*
* JClic - Authoring and playing system for educational activities
*
* Copyright (C) 2000 - 2005 Francesc Busquets & Departament
* d'Educacio de la Generalitat de Catalunya
*
* 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
* (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 General Public License for more details (see the LICENSE file).
*/
package edu.xtec.jclic.project;
import edu.xtec.jclic.*;
import edu.xtec.jclic.activities.panels.Menu;
import edu.xtec.jclic.misc.Utils;
import edu.xtec.util.Domable;
import edu.xtec.util.JDomUtility;
import edu.xtec.util.Messages;
import edu.xtec.util.PersistentSettings;
import edu.xtec.util.ResourceBridge;
import edu.xtec.util.ResourceManager;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.*;
import java.io.File;
import java.util.Iterator;
import javax.swing.*;
import javax.swing.event.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
*
* @author Francesc Busquets (fbusquets@xtec.cat)
* @version 13.10.04
*/
public class LibraryManager implements Domable {
protected DefaultListModel libraries;
protected PlayerSettings settings;
protected boolean modified;
public boolean autoRun;
public static final String AUTO_RUN = "autoRun";
public static final String ELEMENT_NAME = "libraryManager";
private static final String MSG_ID = "libraryManager_";
public static final String PROJECT_LIBRARIES = "project.libraries";
/**
* Creates new LibraryManager
*/
public LibraryManager(PlayerSettings settings) {
this.settings = settings;
libraries = new DefaultListModel();
modified = false;
autoRun = true;
}
public static LibraryManager getLibraryManager(PlayerSettings st, org.jdom.Element e) throws Exception {
LibraryManager lm = new LibraryManager(st);
lm.setProperties(e, null);
return lm;
}
public void setProperties(org.jdom.Element e, Object aux) throws Exception {
JDomUtility.checkName(e, ELEMENT_NAME);
autoRun = JDomUtility.getBoolAttr(e, AUTO_RUN, autoRun);
String[][] sysLibs = getSystemLibraries();
if (sysLibs != null) {
for (int i = 0; i < sysLibs.length; i++) {
LibraryManagerElement lme = new LibraryManagerElement(sysLibs[i][0], sysLibs[i][1], settings.rb.getOptions());
lme.setSystemLib(true);
libraries.addElement(lme);
}
}
Iterator it = e.getChildren(LibraryManagerElement.ELEMENT_NAME).iterator();
while (it.hasNext()) {
libraries.addElement(LibraryManagerElement.getLibraryManagerElement((org.jdom.Element) it.next(), settings.rb.getOptions()));
}
}
public void addNewLibrary(String path, String title) throws Exception {
File f = new File(path);
if (f.exists()) {
ProjectLibrary pl = ProjectLibrary.loadProjectLibrary(path, settings.rb);
title = pl.settings.title;
} else {
if (title == null) {
title = settings.rb.getMsg("libraryManager_mainLibraryTitle");
}
ProjectLibrary pl = ProjectLibrary.createNewProjectLibrary(settings.rb, settings.fileSystem);
pl.settings.title = title;
pl.save(path);
}
libraries.addElement(new LibraryManagerElement(title, path, settings.rb.getOptions()));
}
public org.jdom.Element getJDomElement() {
org.jdom.Element e = new org.jdom.Element(ELEMENT_NAME);
e.setAttribute(AUTO_RUN, JDomUtility.boolString(autoRun));
for (int i = 0; i < libraries.size(); i++) {
LibraryManagerElement lme = (LibraryManagerElement) libraries.get(i);
if (!lme.isSystemLib()) {
e.addContent(lme.getJDomElement());
}
}
return e;
}
public boolean isEmpty() {
return libraries.isEmpty();
}
public ProjectLibrary getAutoStartProjectLibrary() throws Exception {
ProjectLibrary result = null;
if (autoRun && !isEmpty()) {
if (libraries.size() > 1) {
result = selectProjectLibrary(false, false);
} else {
result = ProjectLibrary.loadProjectLibrary(((LibraryManagerElement) libraries.get(0)).path, settings.rb);
if (result != null) {
Menu m = result.getRootMenu();
if (m == null || m.getMenuElementCount() < 1) {
result = null;
}
}
}
}
return result;
}
public ProjectLibrary selectProjectLibrary(boolean allowEdit, boolean selectOnlyEditable) throws Exception {
ProjectLibrary result = null;
if (!libraries.isEmpty() || allowEdit) {
LibraryDialog plDlg = new LibraryDialog(allowEdit, selectOnlyEditable);
plDlg.setVisible(true);
if (plDlg.result != null) {
result = ProjectLibrary.loadProjectLibrary(plDlg.result.path, settings.rb);
}
}
return result;
}
public int getNumLibraries() {
return libraries.getSize();
}
public LibraryManagerElement locateNewProjectLibrary(String path) {
LibraryManagerElement result = null;
ProjectLibrary pl;
ResourceBridge rb = settings.rb;
if (path == null) {
int[] filters = {Utils.JCLIC_FF};
String s = settings.fileSystem.chooseFile(settings.rootPath + File.separator + ".", false, filters, rb.getOptions(), null, rb.getComponent(), false);
if (s != null) {
path = settings.fileSystem.getFullFileNamePath(s);
}
}
if (path != null && !elementExists(path, true)) {
try {
pl = ProjectLibrary.loadProjectLibrary(path, rb);
result = new LibraryManagerElement(pl.settings.title, path, rb.getOptions());
} catch (Exception ex) {
settings.rb.getOptions().getMessages().showErrorWarning(rb.getComponent(), "FILE_ERR_READING", path, ex, null);
}
}
return result;
}
public LibraryManagerElement createNewProjectLibrary(String path, String name) {
LibraryManagerElement result = null;
ResourceBridge rb = settings.rb;
// Unused param "name"
// if(name==null)
// name=rb.getMsg("library_newLibraryName");
if (path == null) {
int[] filters = {Utils.JCLIC_FF};
String s = settings.fileSystem.chooseFile(settings.rootPath + File.separator + "library.jclic", true, filters, rb.getOptions(), null, rb.getComponent(), false);
if (s != null) {
path = settings.fileSystem.getFullFileNamePath(s);
}
}
if (path != null && !elementExists(path, true)) {
ProjectLibrary pl = ProjectLibrary.createNewProjectLibrary(rb, settings.fileSystem);
try {
pl.save(path);
result = new LibraryManagerElement(pl.settings.title, path, rb.getOptions());
} catch (Exception ex) {
settings.rb.getOptions().getMessages().showErrorWarning(rb.getComponent(), "FILE_ERR_SAVING", path, ex, null);
}
}
return result;
}
public boolean elementExists(String path, boolean warn) {
boolean result = false;
for (int i = 0; i < libraries.size(); i++) {
LibraryManagerElement lme = (LibraryManagerElement) libraries.get(i);
if (path.equals(settings.fileSystem.getFullFileNamePath(lme.path))) {
result = true;
if (warn) {
settings.rb.getOptions().getMessages().showAlert(settings.rb.getComponent(), "libraryManager_new_exists");
}
break;
}
}
return result;
}
public LibraryPane getLibraryPane(boolean allowEdit, boolean selectOnlyEditable) {
return new LibraryPane(allowEdit, selectOnlyEditable);
}
public class LibraryPane extends JPanel implements ListSelectionListener {
Action editAction, newLibraryAction, deleteAction;
JList list;
boolean allowEdit, onlyEditable;
LibraryManagerElement current = null;
LibraryPane(boolean allowEdit, boolean selectOnlyEditable) {
super(new BorderLayout());
this.allowEdit = allowEdit;
onlyEditable = selectOnlyEditable;
buildActions();
list = new JList(libraries);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addListSelectionListener(this);
if (list.getModel().getSize() > 0) {
list.setSelectedIndex(0);
}
list.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof LibraryManagerElement) {
LibraryManagerElement lme = (LibraryManagerElement) value;
setIcon(lme.getIcon());
if (!lme.exists || (!lme.editable && onlyEditable) || lme.isSystemLib()) {
setForeground(java.awt.SystemColor.textInactiveText);
}
}
return this;
}
});
add(new JScrollPane(list), BorderLayout.CENTER);
if (allowEdit) {
JPanel buttonsPanel = new JPanel();
buttonsPanel.setOpaque(false);
buttonsPanel.add(new JButton(editAction));
buttonsPanel.add(new JButton(newLibraryAction));
buttonsPanel.add(new JButton(deleteAction));
add(buttonsPanel, BorderLayout.SOUTH);
}
}
void buildActions() {
final edu.xtec.util.Options options = settings.rb.getOptions();
editAction = new AbstractAction(
options.getMsg(MSG_ID + "edit_caption"),
ResourceManager.getImageIcon("icons/edit.gif")) {
public void actionPerformed(ActionEvent ev) {
LibraryManagerElement lme = (LibraryManagerElement) list.getSelectedValue();
if (lme != null) {
try {
if (!settings.promptPassword(LibraryPane.this, null)) {
return;
}
ProjectLibrary pl = ProjectLibrary.loadProjectLibrary(lme.path, settings.rb);
if (pl.editProjectLibrary(LibraryPane.this)) {
if (!pl.settings.title.equals(lme.name)) {
lme.name = pl.settings.title;
modified = true;
list.repaint();
}
}
} catch (Exception ex) {
System.err.println("Unable edit projectLibrary:\n" + ex);
}
}
}
};
editAction.putValue(AbstractAction.SHORT_DESCRIPTION, options.getMsg(MSG_ID + "edit_tooltip"));
editAction.setEnabled(false);
deleteAction = new AbstractAction(
options.getMsg(MSG_ID + "delete_caption"),
ResourceManager.getImageIcon("icons/delete.gif")) {
public void actionPerformed(ActionEvent ev) {
LibraryManagerElement lme = (LibraryManagerElement) list.getSelectedValue();
if (lme != null) {
int currentIndex = list.getSelectedIndex();
try {
if (!settings.promptPassword(LibraryPane.this, null)
|| !(options.getMessages().showQuestionDlg(null, MSG_ID + "delete_confirm", null, "yn") == Messages.YES)) {
return;
}
libraries.removeElement(lme);
modified = true;
list.setSelectedIndex(Math.max(0, currentIndex - 1));
} catch (Exception ex) {
System.err.println("Unable to delete projectLibrary:\n" + ex);
}
}
}
};
deleteAction.putValue(AbstractAction.SHORT_DESCRIPTION, options.getMsg(MSG_ID + "delete_tooltip"));
deleteAction.setEnabled(false);
newLibraryAction = new AbstractAction(
options.getMsg(MSG_ID + "new_caption"),
ResourceManager.getImageIcon("icons/database_new.gif")) {
public void actionPerformed(ActionEvent ev) {
if (!settings.promptPassword(LibraryPane.this, null)) {
return;
}
/*
Object[] opcions = { options.getMsg(MSG_ID+"createNewLibrary"), options.getMsg(MSG_ID+"connectToLibrary"), options.getMsg("CANCEL")};
int n = JOptionPane.showOptionDialog(LibraryPane.this,
options.getMsg(MSG_ID+"new_prompt"),
null,
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
opcions,
opcions[0]);
LibraryManagerElement lme=null;
if(n==JOptionPane.YES_OPTION)
lme=createNewProjectLibrary(null, null);
else if(n==JOptionPane.NO_OPTION)
lme=locateNewProjectLibrary(null);
*/
LibraryManagerElement lme = NewLibraryDlg.getLibraryManagerElement(LibraryManager.this, LibraryPane.this);
if (lme != null) {
modified = true;
libraries.addElement(lme);
list.setSelectedValue(lme, true);
}
}
};
newLibraryAction.putValue(AbstractAction.SHORT_DESCRIPTION, options.getMsg(MSG_ID + "new_tooltip"));
}
public LibraryManagerElement getCurrentSelected() {
return current;
}
public void addListSelectionListener(ListSelectionListener lst) {
list.addListSelectionListener(lst);
}
public void valueChanged(ListSelectionEvent ev) {
if (ev != null && !ev.getValueIsAdjusting()) {
current = (LibraryManagerElement) list.getSelectedValue();
editAction.setEnabled(current != null && current.editable);
deleteAction.setEnabled(current != null && !current.isSystemLib());
//list.setToolTipText(item==null ? null : item.settings.description);
}
}
}
class LibraryDialog extends edu.xtec.util.ExtendedJDialog implements ListSelectionListener {
LibraryManagerElement result = null;
Action selectAction, cancelAction;
LibraryPane pane;
boolean allowEdit, onlyEditable;
LibraryDialog(boolean allowEdit, boolean selectOnlyEditable) {
super(settings.rb.getComponent(), settings.rb.getMsg(MSG_ID + "caption"), true);
this.allowEdit = allowEdit;
onlyEditable = selectOnlyEditable;
pane = new LibraryPane(allowEdit, selectOnlyEditable);
pane.setOpaque(false);
buildActions();
pane.addListSelectionListener(this);
getContentPane().add(pane, BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel();
buttonsPanel.setOpaque(false);
//buttonsPanel.add(new JButton(selectAction));
JButton btSelect = new JButton(selectAction);
btSelect.setDefaultCapable(true);
buttonsPanel.add(btSelect);
buttonsPanel.add(new JButton(cancelAction));
getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
getRootPane().setDefaultButton(btSelect);
pack();
centerOver(settings.rb.getComponent());
pane.list.setSelectedIndex(0);
valueChanged(new ListSelectionEvent(pane.list, 0, 0, false));
valueChanged(null);
}
public void valueChanged(ListSelectionEvent ev) {
if (ev != null && !ev.getValueIsAdjusting()) {
LibraryManagerElement item = pane.getCurrentSelected();
selectAction.setEnabled(item != null && item.exists && (!onlyEditable || item.editable));
}
}
void closeDialog() {
if (modified) {
settings.save();
modified = false;
}
setVisible(false);
}
void buildActions() {
final edu.xtec.util.Options options = settings.rb.getOptions();
selectAction = new AbstractAction(
options.getMsg(MSG_ID + "select_caption"),
ResourceManager.getImageIcon("icons/file_open.gif")) {
public void actionPerformed(ActionEvent ev) {
result = (LibraryManagerElement) pane.list.getSelectedValue();
closeDialog();
}
};
selectAction.putValue(AbstractAction.SHORT_DESCRIPTION, options.getMsg(MSG_ID + "select_tooltip"));
selectAction.setEnabled(false);
cancelAction = new AbstractAction(
options.getMsg(MSG_ID + "cancel_caption"),
ResourceManager.getImageIcon("icons/cancel.gif")) {
public void actionPerformed(ActionEvent ev) {
result = null;
closeDialog();
}
};
cancelAction.putValue(AbstractAction.SHORT_DESCRIPTION, options.getMsg(MSG_ID + "cancel_tooltip"));
}
}
public static String[][] getSystemLibraries() {
String[][] result = null;
try {
String projectLibraries = PersistentSettings.systemPrefs.get(PROJECT_LIBRARIES, "[]");
JSONArray jsa = new JSONArray(projectLibraries);
int numLibraries = jsa.length();
if (numLibraries > 0) {
result = new String[numLibraries][2];
for (int i = 0; i < numLibraries; i++) {
JSONObject jso = jsa.getJSONObject(i);
if (jso != null) {
result[i][0] = jso.getString("name");
result[i][1] = jso.getString("path");
}
if (result[i][0] == null || result[i][1] == null) {
throw new Exception("Invalid settings in JClic system libraries.");
}
}
}
} catch (Exception ex) {
System.err.println("Error reading JClic system libraries: " + ex.getMessage());
result = null;
}
return result;
}
public static void main(String[] args) {
String command = null;
String libName = null;
String libPath = null;
boolean silent = false;
String[][] sysLibs = getSystemLibraries();
boolean err = false;
for (String s : args) {
if(s.equals("-silent")) {
silent = true;
} else if (s.startsWith("-")) {
if (command != null || s.length() == 1) {
err = true;
} else {
command = s.substring(1);
}
} else if (libName == null) {
libName = s;
} else if (libPath == null) {
libPath = s;
} else {
err = true;
}
}
try {
if (err || command == null) {
printUsage();
} else if (command.equals("add") && libName != null && libPath != null) {
JSONArray jsa = new JSONArray();
JSONObject jso;
boolean done = false;
if (sysLibs != null) {
for (int i = 0; i < sysLibs.length; i++) {
String name = sysLibs[i][0];
String path = sysLibs[i][1];
if (libName.equals(name)) {
path = libPath;
done = true;
}
jso = new JSONObject();
jso.put("name", name);
jso.put("path", path);
jsa.put(jso);
}
}
if (!done) {
jso = new JSONObject();
jso.put("name", libName);
jso.put("path", libPath);
jsa.put(jso);
}
try {
PersistentSettings.systemPrefs.put(PROJECT_LIBRARIES, jsa.toString());
PersistentSettings.systemPrefs.flush();
} catch (Exception ex) {
System.err.println("Unable to write system settings. Check your permissions!");
System.err.println(ex.getMessage());
err = true;
}
} else if (command.equals("remove") && libName != null) {
JSONArray jsa = new JSONArray();
JSONObject jso;
boolean done = false;
if (sysLibs != null) {
for (int i = 0; i < sysLibs.length; i++) {
String name = sysLibs[i][0];
String path = sysLibs[i][1];
if (libName.equals(name)) {
done = true;
continue;
}
jso = new JSONObject();
jso.put("name", name);
jso.put("path", path);
jsa.put(jso);
}
}
if (!done) {
System.err.println("ERROR: Library \"" + libName + "\" does not exist!");
err = true;
} else {
try {
PersistentSettings.systemPrefs.put(PROJECT_LIBRARIES, jsa.toString());
PersistentSettings.systemPrefs.flush();
} catch (Exception ex) {
System.err.println("Unable to write system settings. Check your permissions!");
System.err.println(ex.getMessage());
err = true;
}
}
} else if (command.equals("list")) {
if (sysLibs == null || sysLibs.length == 0) {
if (!silent)
System.out.println("There are no system libraries defined!");
} else if (!silent) {
for (int i = 0; i < sysLibs.length; i++) {
System.out.println(sysLibs[i][0] + ": " + sysLibs[i][1]);
}
}
} else {
printUsage();
}
} catch (JSONException ex) {
System.err.println("JSON Error: " + ex.getMessage());
err = true;
}
System.exit(err ? -1 : 0);
}
protected static void printUsage() {
System.out.println(
"JClic System Libraries Manager\n"
+ "\n"
+ "usage: java -cp jclic.jar edu.xtec.jclic.project.LibraryManager -[option] [name] [path]\n"
+ "\n"
+ "Valid options are:\n"
+ "-add name path Adds a new element to the list of system libraries.\n"
+ " 'path' must point to a library.jclic file.\n"
+ "-remove name Removes the library from the system list.\n"
+ "-list Displays a list of the existing system libraries.\n"
+ "-silent Supresses console output (except for errors).\n"
+ "-help Displays this message.\n");
}
}