/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Copyright (C) 2011-2012 Marchand Eric <ricoh51@free.fr>
This file is part of Freegressi.
Freegressi 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 3 of the License, or
(at your option) any later version.
Freegressi 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 Freegressi. If not, see <http://www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package freegressi.tableur;
import freegressi.main.JDialogClipboard;
import freegressi.main.MainModel;
import freegressi.tableur.QuickSort.SortingDirection;
import freegressi.tableur.SpreadSheets.ActiveSheetChangedEvent;
import freegressi.tableur.SpreadSheets.SheetAddedEvent;
import freegressi.tableur.SpreadSheets.SheetDeletedEvent;
import freegressi.tableur.SpreadSheets.SheetDescriptionChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsAngleChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsCSChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnAddedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnDeletedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnModifiedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnMovedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnSortedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnsEditedEvent;
import freegressi.tableur.SpreadSheets.SheetsListener;
import freegressi.tableur.SpreadSheets.SheetsRenamedEvent;
import freegressi.tableur.Tableur.Angle;
import freegressi.utils.KeyBoard;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/**
* Le panel dans lequel vont s'afficher toutes les feuilles ainsi
* que la toolbar
* @author marchand
*/
public class JPanelSheets extends JPanel implements SheetsListener{
private AddSheetAction addSheetAction = new AddSheetAction("Ajouter une feuille vierge",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/inserttable_26x26.png")),
"", 0);
private RenameSheetAction renameSheetAction = new RenameSheetAction("Renommer cette feuille",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/editdoc_26x26.png")),
"", 0);
private DeleteSheetAction deleteSheetAction = new DeleteSheetAction("Supprimer cette feuille",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/Gnome-edit-delete-24.png")),
"", 0);
/** L'action "Editer les colonnes calculées" */
private EditColumnsAction editColumnsAction = new EditColumnsAction("Éditer les variables",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/editdoc_26x26.png")),
"Éditer les variables", 0);
/** L'action "Ajouter une variable (expérimentale ou calculée" */
private AddColumnAction addColumnAction = new AddColumnAction("Ajouter une variable",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/insertcolumns_26x26.png")),
"Ajouter une variable", 0);
/** L'action "Supprimer une variable (expérimentale ou calculée" */
private DeleteColumnAction deleteColumnAction = new DeleteColumnAction("Supprimer une variable",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/deletecolumns_26x26.png")),
"Supprimer une variable", 0);
/** */
private AddLinesAction addLinesAction = new AddLinesAction("Ajouter une ou plusieurs lignes vierges",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/insertrows_26x26.png")),
"Ajouter une ou plusieurs lignes vierges", 0);
/** */
private DeleteLinesAction deleteLinesAction = new DeleteLinesAction("Supprimer une ou plusieurs lignes",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/deleterows_26x26.png")),
"Supprimer une ou plusieurs lignes", 0);
/** */
private SortAction sortAction = new SortAction("Trier une colonne",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/sortascending_26x26.png")),
"Trier une colonne", 0);
/** */
private CopyTableAction copyTableAction = new CopyTableAction("Copier le tableau dans le presse-papier",
new javax.swing.ImageIcon(getClass().getResource("/freegressi/img/copy_26x26.png")),
"Copier le tableau dans le presse-papier", 0);
private JPopupMenu sheetsPopup;
private JPopupMenu sheetPopup;
private JTabbedPane jtpSheets;
private JButton bAngle = new JButton(Angle.RADIAN.getText());
private JToolBar sheetToolBar;
//private JPanelSerie jps;
public JPanelSheets() {
setLayout(new BorderLayout());
createToolBar();
createSheets();
createPopup();
}
private void createToolBar(){
sheetToolBar = new JToolBar(JToolBar.VERTICAL);
sheetToolBar.setFloatable(false); // toolbar fixe
sheetToolBar.setRollover(true);
sheetToolBar.add(editColumnsAction);
sheetToolBar.add(addColumnAction);
sheetToolBar.add(deleteColumnAction);
sheetToolBar.add(addLinesAction);
sheetToolBar.add(deleteLinesAction);
sheetToolBar.add(sortAction);
bAngle.setToolTipText("Changer l'unité d'angles");
bAngle.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (bAngle.getText().equals(Angle.DEGRE.getText())) {
//bAngle.setText(Angle.RADIAN.getText());
SpreadSheets.getInstance().notifySheetsAngleChanged(Angle.RADIAN, true);
} else {
//bAngle.setText(Angle.DEGRE.getText());
SpreadSheets.getInstance().notifySheetsAngleChanged(Angle.DEGRE, true);
}
}
});
sheetToolBar.add(bAngle);
sheetToolBar.add(copyTableAction);
add(sheetToolBar, BorderLayout.WEST);
// Cacher la toolbar tant qu'il n'y a pas au moins une feuille
sheetToolBar.setEnabled(false);
sheetToolBar.setVisible(false);
}
private void createSheets(){
jtpSheets = new JTabbedPane();
jtpSheets.addChangeListener(new ChangeListener() {
// This method is called whenever the selected tab changes
@Override
public void stateChanged(ChangeEvent evt) {
JTabbedPane pane = (JTabbedPane) evt.getSource();
int sel = pane.getSelectedIndex();
SpreadSheets.getInstance().notifyActiveSheetChanged(sel);
}
});
add(jtpSheets, BorderLayout.CENTER);
}
private void createPopup(){
sheetsPopup = new JPopupMenu();
sheetsPopup.add(new JMenuItem(addSheetAction));
sheetsPopup.add(new JMenuItem(renameSheetAction));
sheetsPopup.add(new JMenuItem(deleteSheetAction));
MouseListener popupListener = new PopupListener();
jtpSheets.addMouseListener(popupListener);
sheetPopup = new JPopupMenu();
sheetPopup.add(new JMenuItem(editColumnsAction));
sheetPopup.add(new JMenuItem(addColumnAction));
sheetPopup.add(new JMenuItem(deleteColumnAction));
sheetPopup.add(new JMenuItem(addLinesAction));
sheetPopup.add(new JMenuItem(deleteLinesAction));
sheetPopup.add(new JMenuItem(sortAction));
sheetPopup.add(new JMenuItem(copyTableAction));
}
/**
* Ajoute un panneau sheet au jtpSheets
* @param sheet
* @param title
*/
private void addUISheet(Tableur sheet) {
JPanelSerie jps = new JPanelSerie(sheet, sheetPopup);
//UndoRedo.getInstance().addUndoRedoListener(jps);
//jtpSheets.addTab(title, jspV);
jtpSheets.addTab(sheet.getName(), jps);
int index = jtpSheets.getTabCount() - 1;
jtpSheets.setTabComponentAt(index, new ButtonTabComponent(jtpSheets));
jtpSheets.setSelectedIndex(index);
}
@Override
public void sheetDescriptionChanged(SheetDescriptionChangedEvent event) {
for (int i = 0; i < jtpSheets.getTabCount(); i++){
JPanelSerie jps = (JPanelSerie)jtpSheets.getComponentAt(i);
if (jps.getSheet() == event.getSheet()){
jps.setSheetDescription(event.getNewDescription());
break;
}
}
}
@Override
public void sheetsCSChanged(SheetsCSChangedEvent event) {
// throw new UnsupportedOperationException("Not supported yet.");
}
/**
* La classe qui permet d'éditer les variables calculées
*/
class EditColumnsAction extends AbstractAction {
public EditColumnsAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
// Désactiver la gestion de Ctl Z et Ctl Y par la classe KeyBoard
KeyBoard.setUndoRedo(false);
JDialogEditColumns jdec = new JDialogEditColumns(null);
EditColumnsModel.getInstance().addListener(jdec);
EditColumnsModel.getInstance().startEditing();
jdec.setVisible(true);
EditColumnsModel.getInstance().removeListener(jdec);
// Réactiver
KeyBoard.setUndoRedo(true);
}
}
/**
* La classe qui permet d'ajouter une nouvelle variable
*/
class AddColumnAction extends AbstractAction {
public AddColumnAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Tableur sheet = SpreadSheets.getInstance().getActiveSheet();
if (sheet == null)
throw new NullPointerException("Pas de tableur actif");
JDialogNewOrModifyVar jdnv = new JDialogNewOrModifyVar(null, sheet, JDialogNewOrModifyVar.ModeEditionVariable.NOUVELLE_VARIABLE, null);
jdnv.setVisible(true);
if (jdnv.isOk()) {
SpreadSheets.getInstance().notifyColumnAdded(jdnv.getTypeVariable(), jdnv.getNom(),
jdnv.getUnite(), jdnv.getExpression());
}
}
}
/**
* La classe qui permet de supprimer une variable
*/
class DeleteColumnAction extends AbstractAction {
public DeleteColumnAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
JPanelSerie jps = (JPanelSerie)jtpSheets.getSelectedComponent();
Tableur sheet = SpreadSheets.getInstance().getActiveSheet();
if (sheet == null)
throw new NullPointerException("Pas de tableur");
int[] colonnes = jps.getTable().getSelectedColumns();
int total = colonnes.length;
// Vérif que des colonnes sont sélectionnées
if (colonnes.length == 0) {
JOptionPane.showMessageDialog(null, "Vous devez sélectionner des colonnes pour pouvoir les supprimer!");
return;
}
// Vérif que la première colonne n'est pas supprimée
for (int i = 0; i < colonnes.length; i++) {
if (colonnes[i] == 0) {
JOptionPane.showMessageDialog(null, "La première colonne n'est pas supprimable!");
return;
}
}
// Vérif que des colonnes ne dépendent pas des colonnes sélectionnées
ArrayList<Colonne> listeColonnesDependantes = sheet.donneListeColonnesDependantesMultiples(colonnes);
total += listeColonnesDependantes.size();
// Construction de la chaine correspondant à la liste des noms à supprimer
String str = "";
String[] tabNoms = sheet.donneTableauDeNoms(colonnes);
for (int i = 0; i < tabNoms.length; i++) {
str += tabNoms[i];
if (i != tabNoms.length - 1) {
str += ", ";
}
}
int[] colonnes2 = new int[listeColonnesDependantes.size()];
if (!listeColonnesDependantes.isEmpty()) {
str += " et ";
for (int i = 0; i < listeColonnesDependantes.size(); i++) {
Colonne colonne = listeColonnesDependantes.get(i);
str += colonne.getColonneDescription().getNom();
colonnes2[i] = sheet.indexOfDebug(colonne) + 1;
if (i != listeColonnesDependantes.size() - 1) {
str += ", ";
}
}
}
String message = "Voulez-vous vraiment supprimer les colonnes sélectionnées";
if (listeColonnesDependantes.isEmpty()) {
message += "? : \n" + str;
} else {
message += "\nainsi que les colonnes qui en dépendent? : \n" + str;
}
// Ok c'est bon, on demande confirmation
Object[] options = {"Oui", "Non"};
int n = JOptionPane.showOptionDialog(null,
message, "Attention",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
null, //do not use a custom Icon
options, //the titles of buttons
options[0]); //default button title
if (n == 0) { // la réponse est oui
// construction de la liste des numéros de colonne à supprimer
int[] colonnes3 = new int[total];
System.arraycopy(colonnes, 0, colonnes3, 0, colonnes.length);
System.arraycopy(colonnes2, 0, colonnes3, colonnes.length, colonnes2.length);
String[] names = SpreadSheets.getInstance().getActiveSheet().donneTableauDeNoms(colonnes3);
SpreadSheets.getInstance().notifyColumnsDeleted(colonnes3);
}
}
}
/**
* La classe qui permet d'ajouter une nouvelle ligne
*/
class AddLinesAction extends AbstractAction {
public AddLinesAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
JPanelSerie jps = (JPanelSerie)jtpSheets.getSelectedComponent();
Tableur sheet = SpreadSheets.getInstance().getActiveSheet();
if (sheet == null)
throw new NullPointerException("Pas de tableur");
JDialogAjouterLignes jdal = new JDialogAjouterLignes(null, sheet.getRowCount());
jdal.setVisible(true);
if (jdal.isOk()) {
int nombreLignes = (Integer) jdal.getsAjout().getValue();
int ligne;
if (sheet.getRowCount() != 0) {
ligne = (Integer) jdal.getsMax().getValue();
} else {
ligne = 0;
}
if (jdal.getCombo().getSelectedIndex() == 0) { // Après
sheet.ajouteNLignesVierges(nombreLignes, ligne);
} else { // Avant
sheet.ajouteNLignesVierges(nombreLignes, ligne - 1);
}
}
jdal.dispose();
}
}
/**
* La classe qui permet de supprimer des lignes
*/
class DeleteLinesAction extends AbstractAction {
public DeleteLinesAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
JPanelSerie jps = (JPanelSerie)jtpSheets.getSelectedComponent();
Tableur sheet = SpreadSheets.getInstance().getActiveSheet();
if (sheet == null)
throw new NullPointerException("Pas de tableur");
int[] lignes = jps.getTable().getSelectedRows();
if (lignes.length == 0) {
JOptionPane.showMessageDialog(null, "Vous devez sélectionner des lignes pour pouvoir les supprimer!");
return;
}
Object[] options = {"Oui", "Non"};
int n = JOptionPane.showOptionDialog(null,
"Voulez-vous vraiment supprimer les lignes sélectionnées?", "Attention",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
null, //do not use a custom Icon
options, //the titles of buttons
options[0]); //default button title
if (n == 0) { // la réponse est oui
sheet.notifySupprimerLignes(lignes);
}
}
}
/**
* La classe qui permet de trier une colonne
*/
class SortAction extends AbstractAction {
public SortAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Tableur sheet = SpreadSheets.getInstance().getActiveSheet();
List<String> names = sheet.donneListeNoms();
JDialogSortColumn jdsc = new JDialogSortColumn(null, names);
jdsc.setVisible(true);
if (jdsc.isOk()) {
SortingDirection sd = jdsc.getSortDirection();
String name = jdsc.getSortName();
SpreadSheets.getInstance().notifySheetsSortColumn(name, sd);
}
jdsc.dispose();
}
}
/**
* La classe qui permet de copier des cellules dans le presse papier
*/
class CopyTableAction extends AbstractAction {
public CopyTableAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
Tableur sheet = SpreadSheets.getInstance().getActiveSheet();
if (sheet == null)
throw new NullPointerException("Pas de tableur");
JDialogClipboard jdc = new JDialogClipboard(null, JDialogClipboard.JDialogClipboardType.TOCLIPBOARD, sheet.toCSV());
jdc.setVisible(true);
if (jdc.isOk()) {
String text = jdc.getText();
StringSelection stringSelection = new StringSelection(text);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null);
}
jdc.dispose();
}
}
/* **********************************************************************
*
* Gestion des feuilles par popup
*
*********************************************************************** */
class PopupListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
maybeShowPopup(e);
}
@Override
public void mouseReleased(MouseEvent e) {
maybeShowPopup(e);
}
private void maybeShowPopup(MouseEvent e) {
if (e.isPopupTrigger() && jtpSheets.getTabCount() > 0) {
sheetsPopup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
private class AddSheetAction extends AbstractAction {
public AddSheetAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
MainModel.getInstance().notifyNewSheet();
}
}
private class RenameSheetAction extends AbstractAction {
public RenameSheetAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
String init = SpreadSheets.getInstance().getActiveSheet().getName();
String ans = JOptionPane.showInputDialog(null, "Nouveau nom", init);
if (ans == null) return;
JPanelSerie jps = (JPanelSerie)jtpSheets.getSelectedComponent();
Tableur sheet = jps.getSheet();
SpreadSheets.getInstance().notifySheetRenamed(sheet, ans, true);
}
}
private class DeleteSheetAction extends AbstractAction {
public DeleteSheetAction(String text, ImageIcon icon, String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
@Override
public void actionPerformed(ActionEvent e) {
JPanelSerie jps = (JPanelSerie)jtpSheets.getSelectedComponent();
Tableur sheet = jps.getSheet();
SpreadSheets.getInstance().notifySheetDeleted(sheet, true);
}
}
/* **********************************************************************
*
* Les feuilles
*
*********************************************************************** */
@Override
public void activeSheetChanged(ActiveSheetChangedEvent event) {
}
@Override
public void sheetAdded(SheetAddedEvent event) {
addUISheet(event.getSheet());
sheetToolBar.setEnabled(true);
sheetToolBar.setVisible(true);
}
@Override
public void sheetDeleted(SheetDeletedEvent event) {
Tableur sheet = event.getSheet();
for (int i = 0; i < jtpSheets.getTabCount(); i++){
JPanelSerie jps = (JPanelSerie)jtpSheets.getComponentAt(i);
if (jps.getSheet() == sheet){
jtpSheets.remove(i);
break;
}
}
if (jtpSheets.getTabCount() == 0){
sheetToolBar.setVisible(false);
}
}
@Override
public void sheetRenamed(SheetsRenamedEvent event) {
Tableur sheet;
int index = -1;
for (Component comp : jtpSheets.getComponents()){
if (comp instanceof JPanelSerie){
index++;
sheet = ((JPanelSerie)comp).getSheet();
if (sheet.equals(event.getSheet())){
jtpSheets.setTitleAt(index, sheet.getName());
return;
}
}
}
}
@Override
public void columnAdded(SheetsColumnAddedEvent event) {
}
@Override
public void columnDeleted(SheetsColumnDeletedEvent event) {
}
@Override
public void angleChanged(SheetsAngleChangedEvent event) {
bAngle.setText(event.getNewAngle().getText());
}
@Override
public void columnModified(SheetsColumnModifiedEvent event) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void columnSorted(SheetsColumnSortedEvent event) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void columnMoved(SheetsColumnMovedEvent event) {
//throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void columnsEdited(SheetsColumnsEditedEvent event) {
//throw new UnsupportedOperationException("Not supported yet.");
}
}