All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.widget.editor.Editor Maven / Gradle / Ivy

There is a newer version: 1.1.1
Show newest version
/* *##% Graphical Widget
 * Copyright (C) 2004 - 2008 CodeLutin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser 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 General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * . ##%*/

/* *
 * Editor.java
 *
 * Created: 6 août 2006 10:42:11
 *
 * @author poussin
 * @version $Revision: 233 $
 *
 * Last update: $Date: 2009-12-02 18:00:27 +0100 (mer., 02 déc. 2009) $
 * by : $Author: echatellier $
 */

package org.nuiton.widget.editor;

import static org.nuiton.i18n.I18n._;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentListener;
import javax.swing.text.TextAction;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * L'idee de cette editor, est qu'il ne fait rien lui meme, mais delegue a un
 * autre editeur enregistré. L'enregistrement ce fait par le nom de la classe
 * sous forme de String, ce qui permet d'enregistrer des editeurs qui ne peuvent
 * pas etre chargé car il manque des jars. Par exemple NetBeansEditor qui
 * demande beaucoup de jar, peu ne pas etre chargé convenablement, dans ce cas
 * un autre editeur sera choisi.
 * 

* L'ordre d'enregistrement est important. Le premier editor enregistré sera le * premier editeur essayé. *

* Si l'on souhaite creer un nouvel editeur, il faut implanter * {@link EditorInterface} et etendre au moins {@link Component} *

* Si aucun editeur n'est trouvé alors {@link DefaultEditor} est utilisé *

* Editeur permet d'utiliser Ctrl-s pour sauver le fichier courant quel que soit * l'editeur. * * @author poussin */ public class Editor extends JPanel implements EditorInterface { /** serialVersionUID */ private static final long serialVersionUID = 5820456710194699050L; /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(Editor.class); static protected EditorInterface DEFAULT_EDITOR = new DefaultEditor(); static { registered = new ArrayList(); // we try to automatic register some Editor addEditor(SDocEditor.class.getName()); addEditor(JEditEditor.class.getName()); addEditor(RSyntaxEditor.class.getName()); } /** tous les Editors enregistré */ static protected List registered; /** * register new editor * * @return the new registered Editor, or null, if new editor can't be * instanciant. */ static EditorInterface addEditor(String editorClassName) { try { Class editorClass = Class.forName(editorClassName); EditorInterface result = (EditorInterface) editorClass .newInstance(); registered.add(result); return result; } catch (NoClassDefFoundError eee) { if (log.isDebugEnabled()) { log.debug("Can't find your editor class: " + editorClassName, eee); } if (log.isInfoEnabled()) { log.info("Can't find your editor class: " + editorClassName); } } catch (ClassNotFoundException eee) { if (log.isDebugEnabled()) { log.debug("Can't find your editor class: " + editorClassName, eee); } if (log.isInfoEnabled()) { log.info("Can't find your editor class: " + editorClassName); } } catch (ClassCastException eee) { if (log.isDebugEnabled()) { log.debug("Your editor class is not Editor Child: " + editorClassName, eee); } if (log.isInfoEnabled()) { log.info("Your editor class is not Editor Child: " + editorClassName); } } catch (InstantiationException eee) { if (log.isDebugEnabled()) { log.debug("Can't instanciant your Editor class: " + editorClassName, eee); } if (log.isInfoEnabled()) { log.info("Can't instanciant your Editor class: " + editorClassName); } } catch (IllegalAccessException eee) { if (log.isDebugEnabled()) { log.debug("Can't access your Editor class: " + editorClassName, eee); } if (log.isInfoEnabled()) { log.info("Can't access your Editor class: " + editorClassName); } } catch (Exception eee) { if (log.isDebugEnabled()) { log.debug("Error during instanciation of your Editor: " + editorClassName, eee); } if (log.isInfoEnabled()) { log.info("Error during instanciation of your Editor: " + editorClassName, eee); } } return null; } static protected EditorInterface nullEditor = new NullEditor(); /** editor already instanciate for this editor */ protected Map usedEditor = new HashMap(); /** currentEditor is currently opened editor in this editor */ protected EditorInterface currentEditor = nullEditor; /** current opened file */ protected File openedFile = null; /** All document listener registered on this editor */ protected Set documentListeners = new HashSet(); /** All caret listener registered on this editor */ protected Set caretListeners = new HashSet(); /** * If the edited file is modifier, before switch to other or close it, ask * the user if he want save the modification */ protected boolean askIfNotSaved = true; /** force usage of default editor */ protected boolean forceDefault = false; public Editor() { setLayout(new BorderLayout()); addKeyBinding(); close(); } protected void addKeyBinding() { // Add Ctrl-s -> save Action saveAction = new SaveAction(this); KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_S, Event.CTRL_MASK); this.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put( key, "save"); this.getActionMap().put("save", saveAction); } /** * @return the askIfNotSaved */ public boolean isAskIfNotSaved() { return this.askIfNotSaved; } /** * @param askIfNotSaved the askIfNotSaved to set */ public void setAskIfNotSaved(boolean askIfNotSaved) { this.askIfNotSaved = askIfNotSaved; } /** * @return the forceDefault */ public boolean isForceDefault() { return this.forceDefault; } /** * @param forceDefault the forceDefault to set */ public void setForceDefault(boolean forceDefault) { this.forceDefault = forceDefault; } /** * try to find better editor for this file * * @param file * @return the better editor, or Default Editor */ public EditorInterface getEditor(File file) { // if no editor found, DEFAULT_EDITOR will be used EditorInterface editor = DEFAULT_EDITOR; if (!isForceDefault()) { for (EditorInterface e : Editor.registered) { if (e.accept(file)) { editor = e; } } } EditorInterface newEditor = usedEditor.get(editor); try { if (newEditor == null) { // create new instance for this editor newEditor = editor.getClass().newInstance(); usedEditor.put(editor, newEditor); } } catch (InstantiationException eee) { if (log.isDebugEnabled()) { log.debug("Can't instanciant your Editor class: " + editor.getClass().getName(), eee); } if (log.isInfoEnabled()) { log.info("Can't instanciant your Editor class: " + editor.getClass().getName()); } } catch (IllegalAccessException eee) { if (log.isDebugEnabled()) { log.debug("Can't access your Editor class: " + editor.getClass().getName(), eee); } if (log.isInfoEnabled()) { log.info("Can't access your Editor class: " + editor.getClass().getName()); } } return newEditor; } public void setCurrentEditor(EditorInterface editor) { // remove old editor if (this.currentEditor != null) { remove((Component) this.currentEditor); } // remove all listener on old editor for (DocumentListener l : documentListeners) { this.currentEditor.removeDocumentListener(l); } for (CaretListener l : caretListeners) { this.currentEditor.removeCaretListener(l); } this.currentEditor = editor; // and add all listener on new editor for (DocumentListener l : documentListeners) { this.currentEditor.addDocumentListener(l); } for (CaretListener l : caretListeners) { this.currentEditor.addCaretListener(l); } // put new editor as child add((Component) editor, BorderLayout.CENTER); } /** * @return the currentEditor */ public EditorInterface getCurrentEditor() { return this.currentEditor; } /** * @return the openedFile */ public File getOpenedFile() { return this.openedFile; } /** * @param openedFile the openedFile to set */ public void setOpenedFile(File openedFile) { this.openedFile = openedFile; } /** * Closs current file * * @return the current editor */ public boolean close() { if (askAndSaveOrCancel()) { setOpenedFile(null); setCurrentEditor(nullEditor); return true; } return false; } /** * ask the user to save the current opened file if necessary (current file * is modified) * * @return false if user awnser Cancel, true otherwize. */ protected boolean askAndSaveOrCancel() { boolean result = true; if (isAskIfNotSaved() && getCurrentEditor().isModified()) { int val = JOptionPane.showConfirmDialog(this, _("nuitonwidgets.editor.saveorcancel")); switch (val) { case JOptionPane.YES_OPTION: save(); result = true; break; case JOptionPane.NO_OPTION: result = true; break; case JOptionPane.CANCEL_OPTION: result = false; break; } } return result; } /** * Save current opened file * * @return true if all is ok */ public boolean save() { File file = getOpenedFile(); boolean result = getCurrentEditor().saveAs(file); return result; } /** * if return true, this editor support this file type. Default implantation * return true * * @param file * @return if return true, this editor support this file type. */ public boolean accept(File file) { return true; } /** * indicate if current opened file has been modified * * @return true if currend file is modified */ public boolean isModified() { boolean result = getCurrentEditor().isModified(); return result; } /** * Replace the current edited file by file passed in argument. When you * overide this method, you must call {@link #setOpenedFile(File)} * * @param file the file to open * @return true if file has been opened */ public boolean open(File file) { boolean result = false; if (askAndSaveOrCancel()) { EditorInterface editor = getEditor(file); result = editor.open(file); if (result) { setOpenedFile(file); setCurrentEditor(editor); } else { close(); } } return result; } /** * Replace the current edited file by file passed in argument * * @param file the file to open * @return true if file has been saved and reopen with new name */ public boolean saveAs(File file) { boolean result = getCurrentEditor().saveAs(file); if (result) { result = open(file); } return result; } /* * (non-Javadoc) * * @see org.nuiton.widget.editor.EditorInterface#getText() */ public String getText() { String result = getCurrentEditor().getText(); return result; } /* * (non-Javadoc) * * @see org.nuiton.widget.editor.EditorInterface#getText() */ public void setText(String text) { getCurrentEditor().setText(text); } /* * @see org.nuiton.widget.editor.EditorInterface#copy() */ @Override public void copy() { currentEditor.copy(); } /* * @see org.nuiton.widget.editor.EditorInterface#cut() */ @Override public void cut() { currentEditor.cut(); } /* * @see org.nuiton.widget.editor.EditorInterface#paste() */ @Override public void paste() { currentEditor.paste(); } @Override public void setEnabled(boolean b) { super.setEnabled(b); currentEditor.setEnabled(b); } /* * @see org.nuiton.widget.editor.EditorInterface#addDocumentListener(javax.swing.event.DocumentListener) */ @Override public void addDocumentListener(DocumentListener listener) { documentListeners.add(listener); getCurrentEditor().addDocumentListener(listener); } /* * @see org.nuiton.widget.editor.EditorInterface#removeDocumentListener(javax.swing.event.DocumentListener) */ @Override public void removeDocumentListener(DocumentListener listener) { documentListeners.remove(listener); getCurrentEditor().removeDocumentListener(listener); } /* * @see org.nuiton.widget.editor.EditorInterface#addCaretListener(javax.swing.event.CaretListener) */ @Override public void addCaretListener(CaretListener listener) { caretListeners.add(listener); getCurrentEditor().addCaretListener(listener); } /* * @see org.nuiton.widget.editor.EditorInterface#removeCaretListener(javax.swing.event.CaretListener) */ @Override public void removeCaretListener(CaretListener listener) { caretListeners.remove(listener); getCurrentEditor().removeCaretListener(listener); } static class SaveAction extends TextAction { /** serialVersionUID */ private static final long serialVersionUID = 4694356772539222176L; /** to use log facility, just put in your code: log.info(\"...\"); */ static private Log log = LogFactory.getLog(SaveAction.class); protected Editor editor; /* Create this object with the appropriate identifier. */ SaveAction(Editor editor) { super("save"); this.editor = editor; } /** * The operation to perform when this action is triggered. * * @param e the action event */ public void actionPerformed(ActionEvent e) { log.info("try to save file"); if (!editor.save()) { log.warn("Unable to save"); } else { log.info("saved ok"); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy