
org.nuiton.math.matrix.viewer.MatrixDimensionPanel Maven / Gradle / Ivy
The newest version!
/*
* #%L
* Nuiton Matrix :: GUI
* %%
* Copyright (C) 2010 - 2020 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
* .
* #L%
*/
package org.nuiton.math.matrix.viewer;
import static org.nuiton.i18n.I18n.t;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.DefaultListModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JToggleButton;
import javax.swing.JToggleButton.ToggleButtonModel;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.math.matrix.MatrixND;
/**
* Panel d'affichage des dimensions.
*
* @author chatellier
* @version $Revision$
*
* Last update : $Date$
* By : $Author$
*/
public class MatrixDimensionPanel extends JPanel implements PropertyChangeListener {
/** serialVersionUID. */
private static final long serialVersionUID = -1919447532660452240L;
/** Class logger. */
private static Log log = LogFactory.getLog(MatrixDimensionPanel.class);
/** Matrix to display (original). */
protected MatrixND matrix;
protected List subPanelList;
protected List matrixDimensionActions;
public MatrixDimensionPanel() {
setLayout(new GridLayout(0, 1));
subPanelList = new ArrayList<>();
matrixDimensionActions = new ArrayList<>();
// default sum all action
matrixDimensionActions.add(new SumAllAction());
}
/**
* Add new action. Protected to force call on MatrixViewerPanel.
*
* @param matrixDimentionAction new action
*/
protected void addMatrixDimentionAction(MatrixDimensionAction matrixDimentionAction) {
matrixDimensionActions.add(matrixDimentionAction);
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
this.matrix = (MatrixND)evt.getNewValue();
buildDimensionPanel();
validate();
repaint();
}
public MatrixND getModifiedMatrix() {
MatrixND reducedMatrix = createAndReduce(matrix);
return reducedMatrix;
}
/** Button model from button containing action instance */
protected static class MatrixActionButtonModel extends ToggleButtonModel {
/** serialVersionUID. */
private static final long serialVersionUID = -5737246124430280412L;
protected MatrixDimensionAction matrixAction;
public MatrixActionButtonModel(MatrixDimensionAction matrixAction) {
this.matrixAction = matrixAction;
}
public MatrixDimensionAction getMatrixAction() {
return matrixAction;
}
}
protected class SubDimensionPanel extends JPanel {
/** serialVersionUID. */
private static final long serialVersionUID = 9170588695850504050L;
protected int index;
protected String semanticName;
protected List> semantic;
/**
* Declaration d'un button group avec possibilité de deselectionne
* tous les boutons (methode setSelected surchargée).
*/
protected ButtonGroup buttonGroup = new ButtonGroup() {
/** serialVersionUID. */
private static final long serialVersionUID = 8214289174634749701L;
@Override
public void setSelected(ButtonModel m, boolean b) {
if (b) {
super.setSelected(m, b);
}
else {
clearSelection();
}
}
};
/*
* Gere a la main le group de bouton, car sinon, lors que le premier
* bouton est sélectionné, on ne peut pas le deselection
protected List buttonList = new ArrayList();*/
protected JList semList;
public SubDimensionPanel(int index, String semanticName, List> semantic) {
super(new GridBagLayout());
this.index = index;
this.semanticName = semanticName;
this.semantic = semantic;
renderSubPanel();
}
protected void renderSubPanel() {
// semantic name
JLabel semName = new JLabel(semanticName);
add(semName, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.CENTER,
GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
int nbActionAdded = 0;
for (MatrixDimensionAction matrixDimensionAction : matrixDimensionActions) {
boolean addSumAll = matrixDimensionAction.canApply(index, semantic);
if (addSumAll) {
// sum all button
JToggleButton sumAll = new JToggleButton(matrixDimensionAction.getIcon());
sumAll.setSelectedIcon(matrixDimensionAction.getSelectedIcon());
sumAll.setModel(new MatrixActionButtonModel(matrixDimensionAction));
sumAll.setToolTipText(matrixDimensionAction.getDescription());
add(sumAll, new GridBagConstraints(1 + nbActionAdded, 0, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
buttonGroup.add(sumAll);
nbActionAdded++;
}
}
// semantic list
//MatrixDimensionFilter filter = matrixDimensionFilters.get(index);
semList = new JList();
List> dimSemantic = semantic;
/*if (filter != null) {
dimSemantic = filter.filterSemantic(dimSemantic);
}*/
SemanticListModel semModel = new SemanticListModel(dimSemantic);
semList.setModel(semModel);
/*if (filter != null) {
ListCellRenderer renderer = filter.getListCellRenderer();
if (renderer != null) {
semList.setCellRenderer(renderer);
}
}*/
add(new JScrollPane(semList), new GridBagConstraints(0, 1, 1 + nbActionAdded, 1, 1, 1,
GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 5, 0), 0, 0));
}
public JList getList() {
return semList;
}
/**
* Return true if user has selected this action.
*/
public boolean isSelected() {
boolean result = false;
MatrixActionButtonModel buttonModel = (MatrixActionButtonModel)buttonGroup.getSelection();
if (buttonModel != null) {
result = true;
}
return result;
}
/**
* Apply the selected action.
*/
public MatrixND apply(MatrixND matrix, int dim) {
MatrixActionButtonModel buttonModel = (MatrixActionButtonModel)buttonGroup.getSelection();
MatrixDimensionAction matrixAction = buttonModel.getMatrixAction();
matrix = matrixAction.apply(matrix, dim);
return matrix;
}
}
/**
* Build dimension panel.
*/
protected void buildDimensionPanel() {
subPanelList.clear();
removeAll();
if (matrix != null) {
int index = 0;
for (List> semantic : matrix.getSemantics()) {
// compute dimension name
String dimensionName = t(matrix.getDimensionName(index));
if (dimensionName == null || dimensionName.isEmpty()) {
dimensionName = t("nuitonmatrix.viewer.dimnameindex", index);
}
SubDimensionPanel dimPanel = new SubDimensionPanel(index, dimensionName, semantic);
add(dimPanel);
subPanelList.add(dimPanel);
index++;
}
}
}
public static class SemanticListModel extends DefaultListModel {
/** serialVersionUID. */
private static final long serialVersionUID = 4384624824457446070L;
protected List> semantic;
public SemanticListModel(List> semantic) {
this.semantic = semantic;
}
@Override
public int getSize() {
return semantic.size();
}
@Override
public Object getElementAt(int index) {
return semantic.get(index);
}
}
/**
* Reduit, somme et filtre la matrice sur les dimensions selectionnés,
* les boutons d'action selections et les filtres enregistrés.
*
* @param matrix initial matrix to reduce
* @return filtred, reduced and sommed matrix
*/
protected MatrixND createAndReduce(MatrixND matrix) {
if (log.isDebugEnabled()) {
log.debug("Matrice before submatrix : " + matrix);
}
// la matrice doit être reduite avant tout et en une seule
// fois pour fonctionner avec des matrices réelles ou des proxy
int[][] dimIndices = new int[subPanelList.size()][];
for (int i = 0; i < subPanelList.size(); i++) {
SubDimensionPanel subDimPanel = subPanelList.get(i);
JList list = subDimPanel.getList();
int [] indList = list.getSelectedIndices();
if (indList.length == 0) {
// si rien n'est selectionné on selectionne tout
list.setSelectionInterval(0, list.getModel().getSize()-1);
indList = list.getSelectedIndices();
}
if (0 < indList.length && indList.length < matrix.getDim(i)) {
dimIndices[i] = indList;
}
}
// reduction effective de la matrice
matrix = matrix.getSubMatrix(dimIndices);
if (log.isDebugEnabled()) {
log.debug("Matrix after submatrix : " + matrix);
}
// Effectue la somme si l'utilisateur a selectionné l'option somme
// dans le panel
for (int d = 0; d < subPanelList.size(); d++) {
SubDimensionPanel subDimPanel = subPanelList.get(d);
// il se peux que le nom soit déjà suffixé d'une précédente filtration
String dimName = matrix.getDimensionName(d);
dimName = StringUtils.removeEnd(dimName, "*");
matrix.setDimensionName(d, dimName);
if (subDimPanel.isSelected()) {
// on ajoute une * au nom de la dimension
// l'action devrait normalement surcharger ce nom
matrix.setDimensionName(d, dimName + "*");
// on applique l'operation
matrix = subDimPanel.apply(matrix, d);
}
if (log.isDebugEnabled()) {
log.debug("Matrix after sum on dim " + d + ": " + matrix);
}
}
if (log.isDebugEnabled()) {
log.debug("Matrix bebore reduce: " + matrix);
}
// arrive ici on a une matrice qui a des tailles de dimension 1
// et un tableau des legende pour chaque dimension
// il faut que la matrice est 2 dimensions
// reduction de la matrice
MatrixND result = matrix.reduce(2);
return result;
}
/**
* Autoselect some dimensions values and some dimensions
* action. And perform rendering.
*
* @param dimSelectedValues selected values in each dimensions
* @param selectedActions selected actions in each dimensions
*/
public void initRenderering(List[] dimSelectedValues,
int[] selectedActions) {
// values selection
for (int dimIndex = 0; dimIndex < dimSelectedValues.length; dimIndex++) {
List selectedValues = dimSelectedValues[dimIndex];
if (selectedValues != null) {
SubDimensionPanel panel = subPanelList.get(dimIndex);
panel.semList.clearSelection();
for (Object value : selectedValues) {
int index = panel.semantic.indexOf(value);
panel.semList.addSelectionInterval(index, index);
}
}
}
// action selection
for (int dimIndex = 0; dimIndex < selectedActions.length; dimIndex++) {
int actionIndices = selectedActions[dimIndex];
SubDimensionPanel panel = subPanelList.get(dimIndex);
int buttonIndex = 0;
Enumeration buttons = panel.buttonGroup.getElements();
while (buttons.hasMoreElements()) {
AbstractButton button = buttons.nextElement();
if (actionIndices == buttonIndex) {
button.setSelected(true);
}
buttonIndex++;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy