Palette browser - fix bug when adding several blocks by ENTER
[scilab.git] / scilab / modules / xcos / src / java / org / scilab / modules / xcos / palette / listener / PaletteBlockKeyListener.java
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2015 - Marcos CARDINOT
4  *
5  * This file must be used under the terms of the CeCILL.
6  * This source file is licensed as described in the file COPYING, which
7  * you should have received as part of this distribution.  The terms
8  * are also available at
9  * http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
10  *
11  */
12
13 package org.scilab.modules.xcos.palette.listener;
14
15 import java.awt.event.KeyEvent;
16 import java.awt.event.KeyListener;
17 import java.util.List;
18
19 import org.scilab.modules.xcos.Xcos;
20 import org.scilab.modules.xcos.graph.XcosDiagram;
21 import org.scilab.modules.xcos.palette.PaletteBlockCtrl;
22 import org.scilab.modules.xcos.palette.PaletteCtrl;
23 import org.scilab.modules.xcos.palette.view.PaletteBlockView;
24 import org.scilab.modules.xcos.palette.view.PaletteBlockView.StatusUI;
25 import org.scilab.modules.xcos.palette.view.PaletteManagerPanel;
26 import org.scilab.modules.xcos.palette.view.PaletteView;
27 import org.scilab.modules.xcos.utils.BlockPositioning;
28 import org.scilab.modules.xcos.utils.XcosConstants;
29 import org.scilab.modules.xcos.utils.XcosConstants.PaletteBlockSize;
30
31 /**
32  * Implement the default key listener for the block
33  * @author Marcos CARDINOT <mcardinot@gmail.com>
34  */
35 public final class PaletteBlockKeyListener implements KeyListener {
36     /** Default constructor */
37     public PaletteBlockKeyListener() {
38     }
39
40     /**
41      * @param e The associated event
42      */
43     @Override
44     public void keyPressed(KeyEvent e) {
45         /** add the selected blocks into the most recent diagram **/
46         if (e.getKeyCode() == KeyEvent.VK_ENTER) {
47             final List<XcosDiagram> allDiagrams = Xcos.getInstance().openedDiagrams();
48             final PaletteBlockCtrl control = ((PaletteBlockView) e.getSource()).getController();
49
50             // No diagram opened: should never happen as Xcos opens an empty
51             // diagram when it is launched
52             int size = allDiagrams.size();
53             assert size != 0;
54
55             final XcosDiagram theDiagram = allDiagrams.get(size - 1);
56             Object[] cells = control.getPaletteCtrl().getSelectedBlocks();
57             if (cells != null) {
58                 BlockPositioning.updatePortsPosition(theDiagram, cells);
59                 theDiagram.addCells(cells);
60             }
61
62         /** deselects blocks and loses focus **/
63         } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE || e.getKeyCode() == KeyEvent.VK_TAB) {
64             PaletteCtrl.clearSelections();
65             PaletteBlockView currentBlockView = ((PaletteBlockView) e.getSource());
66             currentBlockView.transferFocusUpCycle();
67
68         /** toggle selection **/
69         } else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
70             PaletteBlockView currentBlockView = ((PaletteBlockView) e.getSource());
71             boolean isSelected = currentBlockView.getController().isSelected();
72             if ((e.getModifiers() & KeyEvent.CTRL_MASK) == 0) {
73                 PaletteCtrl.clearSelections();
74             }
75             currentBlockView.getController().setSelected(!isSelected); // toggle
76             currentBlockView.requestFocus();
77
78         /** move selection (arrow keys) **/
79         } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
80             getNextBlock(e, 0, 1);
81         } else if (e.getKeyCode() == KeyEvent.VK_UP) {
82             getNextBlock(e, 0, -1);
83         } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
84             getNextBlock(e, 1, 0);
85         } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
86             getNextBlock(e, -1, 0);
87         }
88     }
89
90     /**
91      * Get the next block position and handle the selection status
92      * @param e KeyEvent
93      * @param x Initialize x
94      * @param y Initialize y
95      */
96     // CSOFF: ParameterAssignment
97     private void getNextBlock(KeyEvent e, int x, int y) {
98         PaletteBlockView currentBlockView = ((PaletteBlockView) e.getSource());
99         PaletteBlockSize blockSize = PaletteManagerPanel.getCurrentSize();
100
101         x *= blockSize.getBlockDimension().width + XcosConstants.PALETTE_HMARGIN;
102         x += currentBlockView.getLocation().x;
103
104         y *= blockSize.getBlockDimension().height + XcosConstants.PALETTE_VMARGIN;
105         y += currentBlockView.getLocation().y;
106
107         if (x < 0 || y < 0) {
108             return;
109         }
110
111         try {
112             // gets the current palette view
113             PaletteView pview = currentBlockView.getController().getPaletteCtrl().getView();
114
115             // gets the next PaletteBlockView
116             PaletteBlockView nextBlockView = (PaletteBlockView) pview.getComponentAt(x, y);
117
118             // handle keys to decide the selection type
119             boolean ctrlIsDown = (e.getModifiers() & KeyEvent.CTRL_MASK) != 0;
120             boolean isSelected = nextBlockView.getController().isSelected();
121             if (!ctrlIsDown) {
122                 PaletteCtrl.clearSelections();
123                 nextBlockView.getController().setSelected(!isSelected); // toggle
124             } else if (e.getKeyCode() == KeyEvent.VK_SPACE) {
125                 nextBlockView.getController().setSelected(!isSelected); // toggle
126             } else if (!isSelected) {
127                 nextBlockView.setStatusUI(StatusUI.HOVER);
128             }
129
130             pview.scrollRectToVisible(nextBlockView.getBounds());
131             nextBlockView.requestFocus();
132             if (currentBlockView.getStatusUI().equals(StatusUI.HOVER)) {
133                 currentBlockView.setStatusUI(StatusUI.NON_SELECTED);
134             }
135         } catch (ClassCastException err) {
136         } catch (NullPointerException err) {
137         }
138     }
139
140     /**
141      * Not used
142      * @param e Not used
143      */
144     @Override
145     public void keyReleased(KeyEvent e) {
146     }
147
148     /**
149      * Not used
150      * @param e Not used
151      */
152     @Override
153     public void keyTyped(KeyEvent e) {
154     }
155 }