/* * codjo.net * * Common Apache License 2.0 */ package net.codjo.segmentation.gui.editor; import net.codjo.expression.help.FunctionHelp; import net.codjo.gui.toolkit.waiting.WaitingPanel; import net.codjo.variable.basic.BasicVariableReplacer; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.DefaultListCellRenderer; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JList; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.UIManager; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.Document; import javax.swing.text.SimpleAttributeSet; import javax.swing.undo.CannotRedoException; import javax.swing.undo.CannotUndoException; import javax.swing.undo.UndoManager; import org.apache.log4j.Logger; /** * La partie logique du main panel. prends en entr�e la liste des fields et la liste des fontions. La listes * des op�ration est cod� en dur ! * * @author Lajmi */ class EditorMainPanelLogic { private static final Logger APP = Logger.getLogger(EditorMainPanelLogic.class); private EditorMainPanelGui editorMainPanelGui = new EditorMainPanelGui(); private UndoAction undoAction = new UndoAction(); private RedoAction redoAction = new RedoAction(); private UndoManager undoManager = new UndoManager(); private AttributeSet defaultAttributeSet = new SimpleAttributeSet(); private HighlightingStyledDocument document = new HighlightingStyledDocument(); private JPopupMenu popupMenu = new JPopupMenu(); private OperatorHelper operators = new OperatorHelper(); private JListMouseListener jListMouseListener = new JListMouseListener(); private JListKeyListener jListKeyListener = new JListKeyListener(); private WaitingPanel waitingPanel; private HelpStyle helpStyle; private List<Map> listOfMaptoReplaced = new ArrayList<Map>(); private Map fieldMap; private Object[] fieldsDataList; private List<FunctionHelp> functionsList; private Object[] functionDataList; /** * Constructeur de base * * @param fieldMap la Map des Fields : Key : TABLE$COL (<b>String</b>), value : LogicalName * @param functionsList la liste des fontions <b>FunctionHelp</b> */ EditorMainPanelLogic(Map fieldMap, List<FunctionHelp> functionsList, WaitingPanel waitingPanel) { this.functionsList = functionsList; this.functionDataList = functionsList.toArray(); this.fieldMap = fieldMap; this.fieldsDataList = fieldMap.values().toArray(); Arrays.sort(this.fieldsDataList); this.waitingPanel = waitingPanel; initialiseDataListsItems(); initialiseEditorAndHelpStyles(); initialiseUndoRedoButtons(); initialiseListeners(); } private void initialiseEditorAndHelpStyles() { listOfMaptoReplaced.add(fieldMap); document.setColumns(fieldMap.values()); document.setFunctions(functionsList); document.setOperations(operators.getAllOperators()); editorMainPanelGui.getExpressionTextPane().setStyledDocument(document); helpStyle = new HelpStyle(editorMainPanelGui, functionsList, operators.getAllOperators()); } private void initialiseUndoRedoButtons() { JButton undoButton = editorMainPanelGui.getUndoButton(); JButton redoButton = editorMainPanelGui.getRedoButton(); undoButton.setAction(undoAction); redoButton.setAction(redoAction); } private void initialiseDataListsItems() { editorMainPanelGui.getFunctionJList().setListData(functionDataList); editorMainPanelGui.getFunctionJList().setCellRenderer(new FunctionListRenderer()); editorMainPanelGui.getFamilyFieldJList().setListData(fieldsDataList); editorMainPanelGui.getOperationsJList().setListData(operators.getAllOperators().toArray()); } private void initialiseListeners() { // Ajout du listner des listes jListMouseListener = new JListMouseListener(); jListKeyListener = new JListKeyListener(); editorMainPanelGui.getFunctionJList().addMouseListener(jListMouseListener); editorMainPanelGui.getFamilyFieldJList().addMouseListener(jListMouseListener); editorMainPanelGui.getFamilyFieldJList().addMouseListener(new FieldListRightClickMouseListener()); editorMainPanelGui.getOperationsJList().addMouseListener(jListMouseListener); MyListSelectionListener selectionListener = new MyListSelectionListener(); editorMainPanelGui.getFunctionJList().addListSelectionListener(selectionListener); editorMainPanelGui.getFamilyFieldJList().addListSelectionListener(selectionListener); editorMainPanelGui.getOperationsJList().addListSelectionListener(selectionListener); editorMainPanelGui.getFunctionJList().addKeyListener(jListKeyListener); editorMainPanelGui.getFamilyFieldJList().addKeyListener(jListKeyListener); editorMainPanelGui.getOperationsJList().addKeyListener(jListKeyListener); // ajout du listener de Undo et redo editorMainPanelGui.getExpressionTextPane().getStyledDocument() .addUndoableEditListener(new ExpressionUndoableEditListener()); editorMainPanelGui.getExpressionTextPane().addKeyListener(new TextPaneKeyListener()); } public void addStringsStyle(StringsStyle stringsStyle) { document.addStringsStyle(stringsStyle); } MouseListener getjListMouseListener() { return jListMouseListener; } public Map getFieldMap() { return fieldMap; } /** * le getter de l'interface graphique. * * @return le panel � placer dans l'IHM */ public EditorMainPanelGui getEditorMainPanelGui() { return editorMainPanelGui; } /** * use this method to initalize the TextPane with a text * * @param expression chaine de caract�res */ public void setExpression(String expression) { for (Object aListOfMaptoReplaced : listOfMaptoReplaced) { Map map = (Map)aListOfMaptoReplaced; expression = BasicVariableReplacer.replaceKeysPerValues(expression, map); } getEditorMainPanelGui().getExpressionTextPane().setText(expression); } /** * the method replace the columns logical names by the SRC_TAB$COL (for example) * * @return the edited Expression */ public String getExpression() { Document doc = getEditorMainPanelGui().getExpressionTextPane().getDocument(); String expressionLogic; try { expressionLogic = doc.getText(0, doc.getEndPosition().getOffset() - 1); for (Object aListOfMaptoReplaced : listOfMaptoReplaced) { Map map = (Map)aListOfMaptoReplaced; expressionLogic = BasicVariableReplacer.replaceValuesPerKeys(expressionLogic, map); } } catch (BadLocationException ex) { expressionLogic = "ERROR"; } return expressionLogic; } /** * determine si le caret position est dans des parentheses ou non. * * @param text le text * @param caretPosition ou est le curseur * * @return true si le caret est apres ( et false si on est apres ) ou rien */ boolean isInParentheses(String text, int caretPosition) { String part = text.substring(0, caretPosition); int indexOpen = part.lastIndexOf("("); int indexClose = part.lastIndexOf(")"); return indexOpen > indexClose; } public void addExternalPanel(JPanel panel) { editorMainPanelGui.addExternalPanel(panel); } public void addMapToBeReplaced(Map toBeReplaced) { listOfMaptoReplaced.add(toBeReplaced); } public void addLeftPanel(JPanel leftPanel) { editorMainPanelGui.addLeftPanel(leftPanel); } void insertText(String text) { try { JTextPane expression = editorMainPanelGui.getExpressionTextPane(); expression.getDocument().insertString(expression.getCaretPosition(), text, defaultAttributeSet); } catch (Exception ex) { APP.error(ex.getMessage(), ex); } } public void initFieldListPopupMenu(ValueListPanel listPanel) { JMenuItem item = new JMenuItem("Afficher les valeurs"); item.addActionListener(new ColumnsListListener(listPanel, fieldMap, this.getEditorMainPanelGui().getFamilyFieldJList(), waitingPanel)); popupMenu.add(item); } private class MyListSelectionListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent event) { Object obj = ((JList)event.getSource()).getSelectedValue(); String help = ""; if (obj instanceof FunctionHelp) { help = ((FunctionHelp)obj).getHelp(); } else if (obj instanceof OperatorHelper.OperatorHelp) { help = ((OperatorHelper.OperatorHelp)obj).getHelp(); } try { editorMainPanelGui.setLogText(help); helpStyle.colorLog(help); } catch (BadLocationException ex) { APP.error(ex.getMessage(), ex); } } } // listener sur les listes pour inserer l'�l�ment selectionn� dans la position // du curseur dans le text private class JListMouseListener extends MouseAdapter { @Override public void mouseClicked(MouseEvent event) { Object obj = ((JList)event.getSource()).getSelectedValue(); String value; if (obj instanceof FunctionHelp) { value = ((FunctionHelp)obj).getFunctionName(); } else { value = obj.toString(); } if (event.getClickCount() == 2) { JTextPane expression = editorMainPanelGui.getExpressionTextPane(); try { expression.getDocument().insertString(expression.getCaretPosition(), value, defaultAttributeSet); } catch (Exception ex) { APP.error(ex.getMessage(), ex); } } } } private class FieldListRightClickMouseListener extends MouseAdapter { @Override public void mousePressed(MouseEvent evt) { if (evt.isPopupTrigger()) { popupMenu.show(evt.getComponent(), evt.getX(), evt.getY()); } } @Override public void mouseReleased(MouseEvent evt) { if (evt.isPopupTrigger()) { popupMenu.show(evt.getComponent(), evt.getX(), evt.getY()); } } } private class JListKeyListener extends KeyAdapter { @Override public void keyPressed(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ENTER) { Object obj = ((JList)event.getSource()).getSelectedValue(); String value; if (obj instanceof FunctionHelp) { value = ((FunctionHelp)obj).getFunctionName(); } else { value = obj.toString(); } JTextPane expression = editorMainPanelGui.getExpressionTextPane(); try { expression.getDocument().insertString(expression.getCaretPosition(), value, defaultAttributeSet); } catch (Exception ex) { APP.error(ex.getMessage(), ex); } } } } private class ExpressionJPopupMenu extends JDialog { ExpressionJPopupMenu(int posX, int posY, boolean isFunction) { JScrollPane scrollPane; JList workingJList = new JList(); if (isFunction) { workingJList.setListData(fieldsDataList); workingJList.setBackground(new Color(204, 255, 255)); } else { workingJList.setListData(functionDataList); workingJList.setBackground(new Color(204, 255, 204)); } workingJList.setSelectedIndex(0); workingJList.setVisibleRowCount(5); scrollPane = new JScrollPane(workingJList); scrollPane.setBorder(null); // comme les autres listes il inserent dans le text workingJList.addMouseListener(jListMouseListener); workingJList.addKeyListener(jListKeyListener); this.setModal(true); this.setLocationRelativeTo(editorMainPanelGui); this.setResizable(false); this.addKeyListener(new MyKeyAdapter(this)); this.getContentPane().add(scrollPane); this.pack(); this.setLocation(posX, posY); this.setVisible(true); } } private class MyKeyAdapter extends KeyAdapter { private JDialog popupMenu; MyKeyAdapter(JDialog popupMenu) { this.popupMenu = popupMenu; } @Override public void keyPressed(KeyEvent event) { popupMenu.dispose(); } } private class TextPaneKeyListener extends KeyAdapter { private ExpressionJPopupMenu expop = null; @Override public void keyTyped(KeyEvent event) { if (event.isControlDown() && event.getKeyChar() == KeyEvent.VK_SPACE) { int textX = (int)editorMainPanelGui.getExpressionTextPane().getLocationOnScreen() .getX(); int textY = (int)editorMainPanelGui.getExpressionTextPane().getLocationOnScreen() .getY(); int posX = textX + (int)editorMainPanelGui.getExpressionTextPane().getCaret() .getMagicCaretPosition().getX(); int posY = 15 + textY + (int)editorMainPanelGui.getExpressionTextPane().getCaret() .getMagicCaretPosition().getY(); boolean inParentheses = isInParentheses(editorMainPanelGui.getExpressionTextPane().getText(), editorMainPanelGui.getExpressionTextPane().getCaretPosition()); expop = new ExpressionJPopupMenu(posX, posY, inParentheses); } } @Override public void keyPressed(KeyEvent event) { if (event.getKeyChar() == KeyEvent.VK_ESCAPE) { if (expop != null) { expop.setVisible(false); } } } } //Listener des action sur le document text private class ExpressionUndoableEditListener implements UndoableEditListener { public void undoableEditHappened(UndoableEditEvent event) { if (!"modification de style".equalsIgnoreCase( event.getEdit().getPresentationName())) { undoManager.addEdit(event.getEdit()); undoAction.updateUndoState(); redoAction.updateRedoState(); } } } // Action Undo class UndoAction extends AbstractAction { UndoAction() { super("", UIManager.getIcon("undo")); setEnabled(false); } public void actionPerformed(ActionEvent event) { try { undoManager.undo(); } catch (CannotUndoException ex) { ; // it is not possible to undo this operation } updateUndoState(); redoAction.updateRedoState(); } protected void updateUndoState() { if (undoManager.canUndo()) { setEnabled(true); putValue(Action.SHORT_DESCRIPTION, undoManager.getUndoPresentationName()); } else { setEnabled(false); putValue(Action.SHORT_DESCRIPTION, "Undo"); } } } // Redo Action class RedoAction extends AbstractAction { RedoAction() { super("", UIManager.getIcon("redo")); setEnabled(false); } public void actionPerformed(ActionEvent event) { try { undoManager.redo(); } catch (CannotRedoException ex) { ; //it is not possible to redo this operation } updateRedoState(); undoAction.updateUndoState(); } protected void updateRedoState() { if (undoManager.canRedo()) { setEnabled(true); putValue(Action.SHORT_DESCRIPTION, undoManager.getRedoPresentationName()); } else { setEnabled(false); putValue(Action.SHORT_DESCRIPTION, "Redo"); } } } class FunctionListRenderer extends DefaultListCellRenderer { @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); this.setText(((FunctionHelp)value).getFunctionName()); return this; } } }