Index: lutinmatrix/src/java/org/codelutin/math/matrix/gui/MatrixPanelEditor.java diff -u /dev/null lutinmatrix/src/java/org/codelutin/math/matrix/gui/MatrixPanelEditor.java:1.1 --- /dev/null Thu Nov 4 13:54:35 2004 +++ lutinmatrix/src/java/org/codelutin/math/matrix/gui/MatrixPanelEditor.java Thu Nov 4 13:54:30 2004 @@ -0,0 +1,458 @@ +/* *##% +* Copyright (C) 2002, 2003, 2004 Code Lutin, Cédric Pineau, +* Benjamin Poussin +* +* 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. +* +* 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. +*##%*/ + +/* * +* MatrixPanelEditor.java +* +* Created: 4 nov. 2004 +* +* @author Benjamin Poussin +* @version $Revision: 1.1 $ +* +* Mise a jour: $Date: 2004/11/04 13:54:30 $ +* par : $Author: bpoussin $ +*/ + +package org.codelutin.math.matrix.gui; + +import java.awt.*; +import java.awt.datatransfer.*; +import java.awt.event.*; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.swing.*; +import javax.swing.border.*; +import javax.swing.table.*; +import org.codelutin.math.matrix.MatrixException; +import org.codelutin.math.matrix.MatrixHelper; +import org.codelutin.math.matrix.MatrixND; +import org.codelutin.math.matrix.MatrixNDImpl; +import org.codelutin.util.*; + +/** +* Extension de AbstractTableModel pour definir un TableModel avec une +* MatrixND comme support d'information. +*/ +class MatriceTableModel extends AbstractTableModel { + + protected MatrixND m; + /** par defaut, la matrice est editable. */ + protected boolean enabled = true; + + /** + * TableModel basee sur une MatrixND a une ou deux dimensions. + * Pour le moment les matrices de plus de 2 dimensions ne sont pas + * geree.

+ * Pour les matrices 1D :

+ * La premiere dimension represente les colonnes.

+ * Pour les matrices 2D :

+ * La premiere dimension represente les lignes.

+ * La deuxieme dimension represente les colonnes. + * @param m Matrice a afficher dans la table + */ + public MatriceTableModel(MatrixND m) throws MatrixException { + this.m = m; + if (m.getNbDim() > 2) + throw new MatrixException("matrice with more than 2 dimension not supported."); + } + + /** + * Retourne une representation String de la semantique + * de l'element elem de la dimension dim + * @param dim la dimension dans lequel on recherche l'element + * @param elem l'element de la dimension a prendre + * @return une chaine representant l'element. Si l'element est null, la + * chaine vide est retourné + */ + protected String getSemantic(int dim, int elem){ + Object o = m.getSemantics(dim).get(elem); + return (o==null)?"":o.toString(); + } + + public String getColumnName(int column){ + if (m.getNbDim() > 1){ + if (column == 0){ + return ""; + }else{ + return getSemantic(1, column-1); + } + }else { + return getSemantic(0, column); + } + } + + /** + * @return Le nombre de lignes de la table. + */ + public int getRowCount() { + if (m == null || m.getNbDim() < 1) + return 0; + else if (m.getNbDim() > 1) + return m.getDim(0); + else + return 1; + } + + /** + * @return Le nombre de colonnes de la table. + */ + public int getColumnCount() { + if (m == null || m.getNbDim() < 1){ + return 0; + }else if (m.getNbDim() > 1){ + return m.getDim(1) + 1; + }else{ + return m.getDim(0); + } + } + + /** + * @param row La ligne + * @param column La colonnes + * @return L'Object correspondant dans la matrice. + */ + public Object getValueAt(int row, int column) { + // column 0 donc on veut la semantique pour l'afficher + if (column == 0 && m.getNbDim() > 1){ + return getSemantic(0, row); + }else if (m.getNbDim() == 1){ + return ""+m.getValue(column); + } + else{ // m.getNbDim() == 2 + return ""+m.getValue(row, column - 1); + } + } + + /** + * @param obj L'objet a inserer dans la matrice. + * @param row La ligne + * @param column La colonnes + */ + public void setValueAt(Object obj, int row, int column) { + double val = 0; + + if (m.getNbDim() == 1){ + val = m.getValue(column); + } + else{ // m.getNbDim() == 2 + val = m.getValue(row, column - 1); + } + + try{ + val = Double.parseDouble((String)obj); + }catch(Exception eee){ + Logger.getLogger(getClass().getName() + ".setValueAt").log(Level.FINE, "La nouvelle valeur n'est pas convertible en double: " + obj, eee); + } + + if (m.getNbDim() == 1){ + m.setValue(column, val); + }else{ // m.getNbDim() == 2 + m.setValue(row, column - 1, val); + } + fireTableDataChanged(); + } + + /** + * Le modele est rendu editable. + */ + public boolean isCellEditable(int row, int column) { + if(column == 0 && m.getNbDim() > 1) + return false; + return enabled; + } + + /** + * Permet de rendre la table editable ou non . + */ + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + /** + * Par defaut, la classe de la colonne est du type Function.class + */ + public Class getColumnClass(int column){ + return String.class; + } +} + +class MatriceCellRendere extends DefaultTableCellRenderer{ + public Component getTableCellRendererComponent( + JTable table, Object value, boolean isSelected, boolean hasFocus, + int row, int column){ + super.getTableCellRendererComponent(table, value, isSelected + , hasFocus, row, column); + if (table != null) { + JTableHeader header = table.getTableHeader(); + if (header != null) { + setForeground(header.getForeground()); + setBackground(header.getBackground()); + setFont(header.getFont()); + } + } + setBorder(UIManager.getBorder("TableHeader.cellBorder")); + return this; + } +} + +/** +* JPanel contenant une JTable pour afficher une Matrice a une ou deux +* dimension. +*/ +public class MatrixPanelEditor extends JPanel { // MatrixPanelEditor + + private final static int DEFAULT_WIDTH = 150; + private final static int DEFAULT_HEIGHT = 150; + + protected JTable table; + protected MatrixND m; + protected MatriceTableModel tableModel; + protected JScrollPane editArea; + protected JTextArea text; + /** Boolean to autorize table editing. */ + protected boolean enabled = true; + /** Boolean to autorize matrice dimension changes. */ + protected boolean dimensionEdit; + + /** + * Construct a new JPanel to edit matrix. + * @param m the matrice to edit. + * @param dimensionEdit to enabled matrix dimension changes. + */ + public MatrixPanelEditor(MatrixND m, boolean dimensionEdit) { + this(dimensionEdit, DEFAULT_WIDTH, DEFAULT_HEIGHT); + setMatrice(m); + } + + /** + * Construct a new JPanel to edit matrix. + * @param dimensionEdit to enabled matrix dimension changes. + * @param width width prefered for the component + * @param height height prefered for the component + */ + public MatrixPanelEditor(boolean dimensionEdit, int width, int height) { + this.dimensionEdit = dimensionEdit; + setPreferredSize(new Dimension(width, height)); + initObjet(); + } + /** + * Construct a new JPanel to edit matrix. + * @param dimensionEdit to enabled matrix dimension changes. + */ + public MatrixPanelEditor(boolean dimensionEdit) { + this(dimensionEdit, DEFAULT_WIDTH, DEFAULT_HEIGHT); + } + + /** + * Construct a new JPanel to edit matrix. + * Matrix dimension can not change. + */ + public MatrixPanelEditor() { + this(false); + } + + protected void initObjet() { + setLayout(new BorderLayout()); + editArea = new JScrollPane(); + add(editArea, BorderLayout.CENTER); + initDimensionEdit(); + } + + JButton bEdit = null; + protected JButton getButtonEdit() { + if (bEdit == null) { + bEdit = new JButton("Creer matrice"); + bEdit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + String dim; + dim = JOptionPane.showInputDialog(null, + "Dimensions de la matrice (separees par ';')", + "Creer matrice", JOptionPane.DEFAULT_OPTION); + + if (dim != null) { + String [] sdim = dim.split(";"); + int [] idim = new int[sdim.length]; + for(int i=0; i < idim.length; i++){ + idim[i] = Integer.parseInt(sdim[i]); + } + setMatrice(new MatrixNDImpl(idim)); + } + } + }); + add(bEdit, BorderLayout.SOUTH); + } + return bEdit; + } + + /** + * Get the value of dimensionEdit. + * @return value of dimensionEdit. + */ + public boolean isDimensionEdit() { + return dimensionEdit; + } + + /** + * Set the value of dimensionEdit. + * @param v Value to assign to dimensionEdit. + */ + public void setDimensionEdit(boolean v) { + this.dimensionEdit = v; + initDimensionEdit(); + } + + + protected void initDimensionEdit() { + getButtonEdit().setVisible(dimensionEdit); + } + + protected void initObject(MatrixND m) { + if (m == null){ + editArea.setViewportView(null); + } + else if(m.getNbDim() <= 2) { + //pour les matrices 1D et 2D + table = new JTable(); + editArea.setViewportView(table); + table.setModel(tableModel = new MatriceTableModel(m)); + if(table.getColumnCount() > 0){ + table.getColumnModel().getColumn(0).setCellRenderer(new MatriceCellRendere()); + } + table.registerKeyboardAction(getCopyAction(), "Copy", + KeyStroke.getKeyStroke(KeyEvent.VK_C, Event.CTRL_MASK), + JComponent.WHEN_FOCUSED); + text = null; + } else { + //pour les matrices 3D et plus + text = new JTextArea(); + editArea.setViewportView(text); + text.setText(MatrixHelper.encodeToXML(m)); + table = null; + editArea.setColumnHeaderView(null); + } + setEnabled(enabled); + repaint(); + } + + public void setMatrice(MatrixND m)throws MatrixException { + initObject(m); + this.m = m; + } + + public MatrixND getMatrice() { + if (m == null){ + return m; + }else if(m.getNbDim() <= 2){ + return m; + }else{ + return MatrixHelper.decodeFromXML(text.getText()); + } + } + + /** + * Enable the matrix to be edited. By default, the matrix is editable. + */ + public void setEnabled(boolean enabled) { + if (tableModel != null){ + tableModel.setEnabled(enabled); + } + if (text != null){ + text.setEditable(enabled); + } + // si la table n'est pas editable, inutile de laisser le bouton + // de creation de matrice. + if (!enabled && dimensionEdit) { + dimensionEdit = false; + initDimensionEdit(); + } + if (!enabled){ + editArea.setViewportView(null); + } + this.enabled = enabled; + } + + public boolean isEnabled() { + return enabled; + } + + protected ActionListener copyAction; + public ActionListener getCopyAction() { + if (copyAction == null) { + copyAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + copyPerformed(); + } + }; + } + return copyAction; + } + + private void copyPerformed() { + StringSelection contents = new StringSelection(m.toString()); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(contents, contents); + } + + + + /** + * Une petite fonction main pour le test... + */ + public static void main(String[] args) { + JFrame frame = new JFrame(); + MatrixPanelEditor ed = null; + try { + ed = new MatrixPanelEditor(true); + frame.getContentPane().add(ed); + + + // MatriceND m = new MatriceNDImpl(new int[]{4,4}); + // m.set(new int[]{0,0}, new Const(0)); + // m.set(new int[]{0,1}, new Const(1)); + // m.set(new int[]{0,2}, new Const(2)); + // m.set(new int[]{1,0}, new Const(3)); + // m.set(new int[]{1,1}, new Const(4)); + // m.set(new int[]{1,2}, new Const(5)); + + List sem1 = Arrays.asList(new String[]{"toto", "titi", "tutu"}); + List sem2 = Arrays.asList(new String[]{"tata", "tete", "tyty"}); + MatrixND m = new MatrixNDImpl(new List[]{sem1, sem2}); + + ed.setMatrice(m); + //ed.setEnabled(false); + } + catch (MatrixException e) { + e.printStackTrace(); + System.exit(0); + } + + final MatrixPanelEditor mp = ed; + frame.addWindowListener(new WindowAdapter(){ + public void windowClosing(WindowEvent e){ + System.exit(0); + } + }); + frame.pack(); + frame.show(); + } + +} // MatrixPanelEditor +