1 package de.lathanda.eos.gui;
3 import static de.lathanda.eos.gui.icons.Icons.*;
6 import java.awt.Component;
7 import java.awt.Dimension;
9 import java.awt.Rectangle;
10 import java.awt.event.ComponentEvent;
11 import java.awt.event.ComponentListener;
12 import java.awt.event.FocusEvent;
13 import java.awt.event.FocusListener;
14 import java.awt.event.KeyEvent;
15 import java.awt.event.KeyListener;
16 import java.awt.event.MouseAdapter;
17 import java.awt.event.MouseEvent;
18 import java.awt.geom.Rectangle2D;
20 import java.util.TreeSet;
22 import javax.swing.ImageIcon;
23 import javax.swing.JFrame;
24 import javax.swing.JLabel;
25 import javax.swing.JList;
26 import javax.swing.JScrollPane;
27 import javax.swing.JWindow;
28 import javax.swing.ListCellRenderer;
29 import javax.swing.ListSelectionModel;
30 import javax.swing.ToolTipManager;
31 import javax.swing.event.CaretEvent;
32 import javax.swing.event.CaretListener;
33 import javax.swing.text.BadLocationException;
34 import javax.swing.text.Document;
35 import javax.swing.text.AbstractDocument;
36 import javax.swing.text.JTextComponent;
38 import de.lathanda.eos.base.util.GuiToolkit;
39 import de.lathanda.eos.baseparser.AbstractProgram;
40 import de.lathanda.eos.baseparser.AutoCompleteEntry;
41 import de.lathanda.eos.baseparser.AutoCompleteInformation;
42 import de.lathanda.eos.baseparser.AutoCompleteType;
43 import de.lathanda.eos.common.gui.AutoCompleteHook;
44 import de.lathanda.eos.config.Language;
53 public final static ImageIcon[]
ICON = {
64 private int lastPosition = -1;
68 private int startPosition = -1;
72 private boolean active =
false;
76 private JWindow choiceWindow;
80 private TreeSet<AutoCompleteInformation> choiceItems =
new TreeSet<>();
84 private boolean consumeNextKey =
false;
88 private final TooltipList choiceList;
92 private final JTextComponent component;
95 this.component = component;
96 choiceWindow =
new JWindow();
97 choiceWindow.setFocusable(
false);
98 choiceList =
new TooltipList();
100 choiceList.setCellRenderer(
new ChoiceCellRenderer());
101 choiceList.setEnabled(
true);
102 choiceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
103 choiceList.addMouseListener(
new MouseAdapter() {
104 public void mouseClicked(MouseEvent e) {
105 if (e.getClickCount() == 2) {
110 JScrollPane choiceScroll =
new JScrollPane(choiceList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
111 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
112 choiceWindow.getContentPane().add(choiceScroll);
113 component.addCaretListener(
this);
114 component.addKeyListener(
this);
115 component.addFocusListener(
this);
116 mainWindow.addComponentListener(
this);
117 component.addComponentListener(
this);
127 if (base ==
null || base.isUnknown()) {
131 startPosition = position;
132 lastPosition = position;
137 choiceItems.add(aci);
143 choiceItems.add(aci);
159 startPosition = position;
160 lastPosition = position;
163 choiceItems.add(aci);
172 private void showMenue() {
173 if (choiceItems.size() == 0) {
181 choiceWindow.setPreferredSize(
new Dimension(200, 200));
182 Dimension listDimension = choiceList.getPreferredSize();
183 choiceWindow.setSize(listDimension.width + 20, Math.min(listDimension.height + 10, 400));
184 choiceWindow.setVisible(
true);
185 component.requestFocus();
192 int position = component.getCaretPosition();
193 startPosition = position;
194 lastPosition = position;
197 choiceItems.add(entry);
205 private void stop() {
208 choiceWindow.setVisible(
false);
209 choiceList.removeAll();
216 private void setPosition() {
219 box = component.modelToView2D(startPosition - 1);
220 }
catch (BadLocationException e) {
221 box =
new Rectangle(0, 0);
224 int windowX = component.getLocationOnScreen().x + (int) box.getX();
225 int windowY = component.getLocationOnScreen().y + (int) (box.getY() + box.getHeight());
226 choiceWindow.setLocation(windowX, windowY);
232 private void complete() {
233 AutoCompleteInformation choice = choiceList.getSelectedValue();
234 Document text = component.getDocument();
236 if (choice !=
null) {
238 ((AbstractDocument) text).replace(startPosition, lastPosition - startPosition, choice.getTemplate(),
240 int openBracket = startPosition + choice.getTemplate().indexOf(
"(") + 1;
241 if (openBracket != startPosition) {
242 component.setCaretPosition(openBracket);
244 }
catch (BadLocationException e) {
253 private void updateChoices() {
254 Document text = component.getDocument();
256 AutoCompleteInformation selected = choiceList.getSelectedValue();
257 String prefix = text.getText(startPosition, lastPosition - startPosition).toLowerCase();
258 AutoCompleteInformation[] choices = choiceItems.stream()
259 .filter(choice -> choice.getScantext().toLowerCase().startsWith(prefix))
260 .toArray(size ->
new AutoCompleteInformation[size]);
261 if (choices.length == 0) {
264 choiceList.setListData(choices);
265 if (selected !=
null) {
266 choiceList.setSelectedValue(selected,
true);
267 if (choiceList.getSelectedValue() ==
null) {
268 choiceList.setSelectedIndex(0);
271 choiceList.setSelectedIndex(0);
274 }
catch (BadLocationException e) {
284 private void setSelectedItem(
int index) {
285 if (choiceList.getModel().getSize() == 0)
287 int n = index % choiceList.getModel().getSize();
289 n += choiceList.getModel().getSize();
291 choiceList.setSelectedIndex(n);
292 choiceList.ensureIndexIsVisible(n);
296 private class TooltipList
extends JList<AutoCompleteInformation> {
297 private static final long serialVersionUID = -7313420722740426372L;
299 public TooltipList() {
300 ToolTipManager.sharedInstance().registerComponent(
this);
304 public String getToolTipText(MouseEvent me) {
305 int index = locationToIndex(me.getPoint());
307 return "<html><p>" + getModel().getElementAt(index).getTooltip() +
"</p></html>";
319 private static class ChoiceCellRenderer
extends JLabel implements ListCellRenderer<AutoCompleteInformation> {
320 private static final long serialVersionUID = -6215568900839124763L;
323 public Component getListCellRendererComponent(JList<? extends AutoCompleteInformation> list,
324 AutoCompleteInformation value,
int index,
boolean isSelected,
boolean cellHasFocus) {
325 setText(value.getLabel());
326 setIcon(
ICON[value.getType()]);
328 setBackground(Color.BLUE);
329 setForeground(Color.WHITE);
331 setBackground(Color.WHITE);
332 setForeground(Color.BLACK);
334 setEnabled(list.isEnabled());
335 setFont(list.getFont());
346 lastPosition = ce.getDot();
347 if (lastPosition < startPosition) {
356 if (ke.isControlDown() && ke.getKeyCode() == KeyEvent.VK_SPACE) {
359 consumeNextKey =
true;
365 switch (ke.getKeyCode()) {
367 setSelectedItem(choiceList.getSelectedIndex() - 1);
370 case KeyEvent.VK_DOWN:
371 setSelectedItem(choiceList.getSelectedIndex() + 1);
374 case KeyEvent.VK_ENTER:
375 case KeyEvent.VK_TAB:
378 case KeyEvent.VK_ESCAPE:
393 if (consumeNextKey) {
394 consumeNextKey =
false;
399 if (!(Character.isAlphabetic(ke.getKeyChar()) || ke.getKeyChar() ==
'\b')) {
443 if (text.equals(
".")) {
445 start(base, pos + 1);
446 }
else if (text.equals(
":")) {
449 }
catch (BadLocationException e) {
Set< AutoCompleteEntry > getTemplates()
boolean isLockProperties()
void componentMoved(ComponentEvent ce)
void componentHidden(ComponentEvent arg0)
void focusGained(FocusEvent fe)
static final ImageIcon[] ICON
void caretUpdate(CaretEvent ce)
void keyReleased(KeyEvent ke)
void keyTyped(KeyEvent ke)
void keyPressed(KeyEvent ke)
void startClass(AbstractProgram program, int position)
void componentResized(ComponentEvent ce)
void start(AutoCompleteType base, int position)
void focusLost(FocusEvent fe)
void componentShown(ComponentEvent ce)
void insertString(int pos, String text, AbstractProgram program)
AutoCompletion(JTextComponent component, JFrame mainWindow)
AutoCompleteType seekType(int pos)