1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 package org.openflexo.gina.swing.utils;
40
41 import java.awt.BorderLayout;
42 import java.awt.Color;
43 import java.awt.Component;
44 import java.awt.Container;
45 import java.awt.Dimension;
46 import java.awt.Font;
47 import java.awt.Rectangle;
48 import java.awt.event.ActionEvent;
49 import java.awt.event.ActionListener;
50 import java.awt.event.KeyAdapter;
51 import java.awt.event.KeyEvent;
52 import java.awt.event.MouseAdapter;
53 import java.awt.event.MouseEvent;
54 import java.beans.PropertyChangeEvent;
55 import java.beans.PropertyChangeListener;
56 import java.lang.reflect.Type;
57 import java.util.ArrayList;
58 import java.util.Hashtable;
59 import java.util.List;
60 import java.util.Map;
61 import java.util.StringTokenizer;
62 import java.util.Vector;
63 import java.util.logging.Level;
64 import java.util.logging.Logger;
65
66 import javax.swing.AbstractListModel;
67 import javax.swing.BorderFactory;
68 import javax.swing.BoxLayout;
69 import javax.swing.DefaultListCellRenderer;
70 import javax.swing.Icon;
71 import javax.swing.JButton;
72 import javax.swing.JComponent;
73 import javax.swing.JLabel;
74 import javax.swing.JList;
75 import javax.swing.JPanel;
76 import javax.swing.JScrollPane;
77 import javax.swing.JSplitPane;
78 import javax.swing.ListModel;
79 import javax.swing.ListSelectionModel;
80 import javax.swing.ScrollPaneConstants;
81 import javax.swing.SwingConstants;
82 import javax.swing.SwingUtilities;
83 import javax.swing.event.ListSelectionEvent;
84 import javax.swing.event.ListSelectionListener;
85
86 import org.openflexo.connie.Bindable;
87 import org.openflexo.connie.BindingEvaluationContext;
88 import org.openflexo.connie.BindingFactory;
89 import org.openflexo.connie.BindingModel;
90 import org.openflexo.connie.BindingVariable;
91 import org.openflexo.connie.DataBinding;
92 import org.openflexo.connie.DataBinding.BindingDefinitionType;
93 import org.openflexo.connie.binding.BindingPathElement;
94 import org.openflexo.connie.binding.Function;
95 import org.openflexo.connie.binding.Function.FunctionArgument;
96 import org.openflexo.connie.binding.FunctionPathElement;
97 import org.openflexo.connie.binding.IBindingPathElement;
98 import org.openflexo.connie.binding.SimplePathElement;
99 import org.openflexo.connie.expr.BindingValue;
100 import org.openflexo.connie.type.TypeUtils;
101 import org.openflexo.connie.type.Typed;
102 import org.openflexo.gina.model.FIBModelObject.FIBModelObjectImpl;
103 import org.openflexo.gina.swing.utils.BindingSelector.EditionMode;
104 import org.openflexo.gina.swing.utils.table.AbstractModel;
105 import org.openflexo.gina.swing.utils.table.BindingValueColumn;
106 import org.openflexo.gina.swing.utils.table.IconColumn;
107 import org.openflexo.gina.swing.utils.table.StringColumn;
108 import org.openflexo.gina.swing.utils.table.TabularPanel;
109 import org.openflexo.gina.utils.FIBIconLibrary;
110 import org.openflexo.swing.ButtonsControlPanel;
111 import org.openflexo.swing.MouseOverButton;
112 import org.openflexo.swing.VerticalLayout;
113 import org.openflexo.toolbox.HasPropertyChangeSupport;
114 import org.openflexo.toolbox.StringUtils;
115 import org.openflexo.toolbox.ToolBox;
116
117
118
119
120
121
122
123
124 @SuppressWarnings("serial")
125 public class BindingValueSelectorPanel extends AbstractBindingSelectorPanel implements ListSelectionListener {
126
127 static final Logger LOGGER = Logger.getLogger(BindingValueSelectorPanel.class.getPackage().getName());
128
129 private static final String SPECIFY_BASIC_BINDING = "specify_basic_binding";
130 private static final String SPECIFY_COMPOUND_BINDING = "specify_complex_binding";
131
132
133
134
135 final BindingSelector bindingSelector;
136
137
138
139
140 protected JPanel browserPanel;
141
142
143
144
145 protected ButtonsControlPanel _controlPanel;
146
147 protected JButton connectButton;
148 protected JButton cancelButton;
149 protected JButton resetButton;
150 protected JButton expressionButton;
151
152 protected JButton createsButton;
153
154 private final Map<IBindingPathElement, Hashtable<Type, BindingColumnListModel>> _listModels;
155
156 private final Vector<FilteredJList<?>> _lists;
157
158 protected int defaultVisibleColCount = 3;
159
160 protected final EmptyColumnListModel EMPTY_MODEL = new EmptyColumnListModel();
161
162 private BindingColumnListModel _rootBindingColumnListModel = null;
163
164 JLabel currentTypeLabel;
165 private JLabel searchedTypeLabel;
166
167 protected BindingColumnElement currentFocused = null;
168
169 protected BindingValueSelectorPanel(BindingSelector bindingSelector) {
170 super();
171 this.bindingSelector = bindingSelector;
172 _listModels = new Hashtable<>();
173 _rootBindingColumnListModel = null;
174 _lists = new Vector<>();
175 }
176
177 @Override
178 public void delete() {
179 if (_methodCallBindingsModel != null) {
180 _methodCallBindingsModel.delete();
181 _methodCallBindingsModel = null;
182 }
183 for (JList<?> list : _lists) {
184 list.removeListSelectionListener(this);
185 list.setModel(null);
186 }
187 _lists.clear();
188 _listModels.clear();
189 _rootBindingColumnListModel = null;
190 currentFocused = null;
191 }
192
193 public int getIndexOfList(BindingColumnListModel model) {
194 for (int i = 0; i < _lists.size(); i++) {
195 FilteredJList<?> l = _lists.get(i);
196 if (l.getModel() == model) {
197 return i;
198 }
199 }
200 return -1;
201 }
202
203 public Class<?> getAccessedEntity() {
204 Class<?> reply = null;
205 int i = 1;
206 BindingColumnElement last = null;
207 while (listAtIndex(i) != null && listAtIndex(i).getSelectedValue() != null) {
208 last = (BindingColumnElement) listAtIndex(i).getSelectedValue();
209 i++;
210 }
211 if (last != null) {
212 return TypeUtils.getBaseClass(last.getElement().getType());
213 }
214 return reply;
215 }
216
217 public BindingVariable getSelectedBindingVariable() {
218 if (listAtIndex(0) != null && listAtIndex(0).getSelectedValue() != null) {
219 return (BindingVariable) ((BindingColumnElement) listAtIndex(0).getSelectedValue()).getElement();
220 }
221 else if (listAtIndex(0) != null && listAtIndex(0).getModel().getSize() == 1) {
222 return (BindingVariable) listAtIndex(0).getModel().getElementAt(0).getElement();
223 }
224 else {
225 return null;
226 }
227 }
228
229 @Deprecated
230 private static BindingColumnElement findElementMatching(ListModel listModel, String subPartialPath, Vector<Integer> pathElementIndex) {
231 for (int i = 0; i < listModel.getSize(); i++) {
232 if (listModel.getElementAt(i) instanceof BindingColumnElement
233 && ((BindingColumnElement) listModel.getElementAt(i)).getLabel().startsWith(subPartialPath)) {
234 if (pathElementIndex.size() == 0) {
235 pathElementIndex.add(i);
236 }
237 else {
238 pathElementIndex.set(0, i);
239 }
240 return (BindingColumnElement) listModel.getElementAt(i);
241 }
242 }
243 return null;
244 }
245
246 Vector<BindingColumnElement> findElementsMatching(BindingColumnListModel listModel, String subPartialPath) {
247 Vector<BindingColumnElement> returned = new Vector<>();
248 for (int i = 0; i < listModel.getUnfilteredSize(); i++) {
249 if (listModel.getUnfilteredElementAt(i).getLabel().startsWith(subPartialPath)) {
250 returned.add(listModel.getUnfilteredElementAt(i));
251 }
252 }
253 return returned;
254 }
255
256 BindingColumnElement findElementEquals(ListModel<?> listModel, String subPartialPath) {
257 for (int i = 0; i < listModel.getSize(); i++) {
258 if (listModel.getElementAt(i) instanceof BindingColumnElement) {
259 if (((BindingColumnElement) listModel.getElementAt(i)).getLabel() != null
260 && ((BindingColumnElement) listModel.getElementAt(i)).getLabel().equals(subPartialPath)) {
261 return (BindingColumnElement) listModel.getElementAt(i);
262 }
263 }
264 }
265 return null;
266 }
267
268 public Type getEndingTypeForSubPath(String pathIgnoringLastPart) {
269 StringTokenizer token = new StringTokenizer(pathIgnoringLastPart, ".", false);
270 Object obj = null;
271 int i = 0;
272 while (token.hasMoreTokens()) {
273 obj = findElementEquals(listAtIndex(i).getModel(), token.nextToken());
274 i++;
275 }
276 if (obj instanceof BindingColumnElement) {
277 Typed element = ((BindingColumnElement) obj).getElement();
278 return element.getType();
279 }
280 return null;
281 }
282
283 protected class MethodCallBindingsModel extends AbstractModel<FunctionPathElement, Function.FunctionArgument> {
284 public MethodCallBindingsModel(FunctionPathElement functionPathElement) {
285 super(functionPathElement);
286 addToColumns(new IconColumn<Function.FunctionArgument>("icon", 25) {
287 @Override
288 public Icon getIcon(Function.FunctionArgument entity) {
289 return FIBIconLibrary.METHOD_ICON;
290 }
291 });
292 addToColumns(new StringColumn<Function.FunctionArgument>("name", 100) {
293 @Override
294 public String getValue(Function.FunctionArgument arg) {
295 if (arg != null) {
296 return arg.getArgumentName();
297 }
298
299
300
301
302 return "null";
303 }
304 });
305 addToColumns(new StringColumn<Function.FunctionArgument>("type", 100) {
306 @Override
307 public String getValue(Function.FunctionArgument arg) {
308 if (arg != null) {
309 return TypeUtils.simpleRepresentation(arg.getArgumentType());
310 }
311 return "null";
312 }
313 });
314 addToColumns(new BindingValueColumn<Function.FunctionArgument>("value", 250, true) {
315 @Override
316 public DataBinding getValue(Function.FunctionArgument arg) {
317 return getFunctionPathElement().getParameter(arg);
318 }
319
320
321
322
323 @Override
324 public void setValue(Function.FunctionArgument arg, DataBinding aValue) {
325 if (LOGGER.isLoggable(Level.FINE)) {
326 LOGGER.fine("Sets value " + arg + " to be " + aValue);
327 }
328
329 if (arg != null && getFunctionPathElement() != null) {
330
331
332 getFunctionPathElement().setParameter(arg, aValue);
333
334
335
336 BindingValue bv = (BindingValue) bindingSelector.getEditedObject().getExpression();
337 bv.updateParsedBindingPathFromBindingPath();
338
339
340 bindingSelector.getEditedObject().markedAsToBeReanalized();
341
342 }
343
344
345 bindingSelector.fireEditedObjectChanged();
346 }
347
348 @Override
349 public Bindable getBindableFor(DataBinding<?> value, Function.FunctionArgument rowObject) {
350 if (value != null) {
351 return value.getOwner();
352 }
353 return null;
354 }
355
356 @Override
357 public boolean allowsCompoundBinding(DataBinding<?> value) {
358 return true;
359 }
360
361 @Override
362 public boolean allowsNewEntryCreation(DataBinding<?> value) {
363 return false;
364 }
365 });
366 }
367
368
369
370
371
372
373
374
375
376
377 public FunctionPathElement getFunctionPathElement() {
378 return getModel();
379 }
380
381 @Override
382 public Function.FunctionArgument elementAt(int row) {
383 if (row >= 0 && row < getRowCount()) {
384 return getFunctionPathElement().getFunction().getArguments().get(row);
385 }
386 return null;
387 }
388
389 @Override
390 public int getRowCount() {
391 if (getFunctionPathElement() != null) {
392 return getFunctionPathElement().getFunction().getArguments().size();
393 }
394 return 0;
395 }
396
397 @Override
398 public void setModel(FunctionPathElement model) {
399
400 if (model != null) {
401 model.instanciateParameters(bindingSelector.getBindable());
402 }
403 super.setModel(model);
404 }
405
406 @Override
407 public BindingEvaluationContext getBindingEvaluationContext() {
408 return null;
409 }
410
411 public void delete() {
412 for (int i = 0; i < getColumnCount(); i++) {
413 columnAt(i).delete();
414 }
415 }
416 }
417
418 protected class MethodCallBindingsPanel extends TabularPanel {
419 public MethodCallBindingsPanel() {
420 super(getMethodCallBindingsModel(), 3);
421 }
422
423 }
424
425 private MethodCallBindingsModel _methodCallBindingsModel;
426
427 private MethodCallBindingsPanel _methodCallBindingsPanel;
428
429 public MethodCallBindingsPanel getMethodCallBindingsPanel() {
430 if (_methodCallBindingsPanel == null) {
431 _methodCallBindingsPanel = new MethodCallBindingsPanel();
432
433 }
434
435 return _methodCallBindingsPanel;
436 }
437
438 public MethodCallBindingsModel getMethodCallBindingsModel() {
439 if (_methodCallBindingsModel == null) {
440 _methodCallBindingsModel = new MethodCallBindingsModel(null);
441 }
442 return _methodCallBindingsModel;
443 }
444
445 @Override
446 public Dimension getDefaultSize() {
447 int baseHeight;
448
449 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING) {
450 baseHeight = 300;
451 }
452 else {
453 baseHeight = 180;
454 }
455
456 if (bindingSelector.areStaticValuesAllowed() || bindingSelector.areCompoundBindingAllowed()) {
457 baseHeight += 30;
458 }
459
460 return new Dimension(500, baseHeight);
461
462 }
463
464 @Override
465 protected void willApply() {
466 if (editStaticValue && staticBindingPanel != null) {
467 staticBindingPanel.willApply();
468 }
469 }
470
471 private MouseOverButton showHideCompoundBindingsButton;
472
473 private ConstantValuePanel staticBindingPanel;
474
475 @Override
476 protected void init() {
477 if (LOGGER.isLoggable(Level.FINE)) {
478 LOGGER.fine("init() with " + bindingSelector.editionMode + " for " + bindingSelector.getEditedObject());
479 }
480
481 setLayout(new BorderLayout());
482
483 browserPanel = new JPanel();
484 browserPanel.setLayout(new BoxLayout(browserPanel, BoxLayout.X_AXIS));
485 for (int i = 0; i < defaultVisibleColCount; i++) {
486 makeNewJList();
487 }
488
489 _controlPanel = new ButtonsControlPanel() {
490 @Override
491 public String localizedForKeyAndButton(String key, JButton component) {
492 return FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey(key, component);
493 }
494 };
495 connectButton = _controlPanel.addButton("connect", new ActionListener() {
496 @Override
497 public void actionPerformed(ActionEvent e) {
498 bindingSelector.apply();
499 }
500 });
501 cancelButton = _controlPanel.addButton("cancel", new ActionListener() {
502 @Override
503 public void actionPerformed(ActionEvent e) {
504 bindingSelector.cancel();
505 }
506 });
507 resetButton = _controlPanel.addButton("reset", new ActionListener() {
508 @Override
509 public void actionPerformed(ActionEvent e) {
510 bindingSelector.getEditedObject().reset();
511 bindingSelector.apply();
512 }
513 });
514 if (bindingSelector.areBindingExpressionsAllowed()) {
515 expressionButton = _controlPanel.addButton("expression", new ActionListener() {
516 @Override
517 public void actionPerformed(ActionEvent e) {
518 bindingSelector.activateBindingExpressionMode();
519 }
520 });
521 }
522
523 _controlPanel.applyFocusTraversablePolicyTo(_controlPanel, false);
524
525 JPanel optionsPanel = new JPanel();
526 optionsPanel.setLayout(new BorderLayout());
527
528 if (bindingSelector.areCompoundBindingAllowed()) {
529 showHideCompoundBindingsButton = new MouseOverButton();
530 showHideCompoundBindingsButton.setBorder(BorderFactory.createEmptyBorder());
531 showHideCompoundBindingsButton.addActionListener(new ActionListener() {
532 @Override
533 public void actionPerformed(ActionEvent e) {
534 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING) {
535 bindingSelector.activateNormalBindingMode();
536 }
537 else {
538 bindingSelector.activateCompoundBindingMode();
539 }
540 }
541 });
542
543 JLabel showHideCompoundBindingsButtonLabel = new JLabel("", SwingConstants.RIGHT);
544 showHideCompoundBindingsButtonLabel.setFont(new Font("SansSerif", Font.PLAIN, 10));
545 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING) {
546 showHideCompoundBindingsButton.setNormalIcon(FIBIconLibrary.TOGGLE_ARROW_TOP_ICON);
547 showHideCompoundBindingsButton.setMouseOverIcon(FIBIconLibrary.TOGGLE_ARROW_TOP_SELECTED_ICON);
548 showHideCompoundBindingsButton.setToolTipText(FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey(SPECIFY_BASIC_BINDING));
549 showHideCompoundBindingsButtonLabel
550 .setText(FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey(SPECIFY_BASIC_BINDING) + " ");
551 }
552 else {
553 showHideCompoundBindingsButton.setNormalIcon(FIBIconLibrary.TOGGLE_ARROW_BOTTOM_ICON);
554 showHideCompoundBindingsButton.setMouseOverIcon(FIBIconLibrary.TOGGLE_ARROW_BOTTOM_SELECTED_ICON);
555 showHideCompoundBindingsButton
556 .setToolTipText(FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey(SPECIFY_COMPOUND_BINDING));
557 showHideCompoundBindingsButtonLabel
558 .setText(FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey(SPECIFY_COMPOUND_BINDING) + " ");
559 }
560
561 JPanel showHideCompoundBindingsButtonPanel = new JPanel();
562 showHideCompoundBindingsButtonPanel.setLayout(new BorderLayout());
563 showHideCompoundBindingsButtonPanel.add(showHideCompoundBindingsButtonLabel, BorderLayout.CENTER);
564 showHideCompoundBindingsButtonPanel.add(showHideCompoundBindingsButton, BorderLayout.EAST);
565
566 optionsPanel.add(showHideCompoundBindingsButtonPanel, BorderLayout.EAST);
567 }
568
569 if (bindingSelector.areStaticValuesAllowed()) {
570 JPanel optionsWestPanel = new JPanel();
571 optionsWestPanel.setLayout(new VerticalLayout());
572 staticBindingPanel = new ConstantValuePanel(this);
573 optionsWestPanel.add(staticBindingPanel);
574 optionsPanel.add(optionsWestPanel, BorderLayout.WEST);
575 }
576
577 currentTypeLabel = new JLabel(FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey("no_type"), SwingConstants.LEFT);
578 currentTypeLabel.setFont(new Font("SansSerif", Font.ITALIC, 10));
579 currentTypeLabel.setForeground(Color.GRAY);
580
581 searchedTypeLabel = new JLabel("[" + FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey("no_type") + "]", SwingConstants.LEFT);
582 searchedTypeLabel.setFont(new Font("SansSerif", Font.PLAIN, 10));
583 searchedTypeLabel.setForeground(Color.RED);
584
585 JPanel labelPanel = new JPanel();
586 labelPanel.setLayout(new BorderLayout());
587 labelPanel.add(currentTypeLabel, BorderLayout.CENTER);
588 labelPanel.add(searchedTypeLabel, BorderLayout.EAST);
589
590 JComponent topPane;
591
592 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING) {
593 topPane = new JPanel();
594 topPane.setLayout(new BorderLayout());
595
596
597
598
599
600 topPane.add(labelPanel, BorderLayout.SOUTH);
601 }
602 else {
603 topPane = labelPanel;
604 }
605
606 add(topPane, BorderLayout.NORTH);
607
608 JComponent middlePane;
609
610
611
612 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING) {
613 middlePane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JScrollPane(browserPanel,
614 ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
615 getMethodCallBindingsPanel());
616 ((JSplitPane) middlePane).setDividerLocation(0.5);
617 ((JSplitPane) middlePane).setResizeWeight(0.5);
618 }
619 else {
620 middlePane = new JScrollPane(browserPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
621 ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
622 }
623
624 JPanel middlePaneWithOptions = new JPanel();
625 middlePaneWithOptions.setLayout(new BorderLayout());
626 middlePaneWithOptions.add(middlePane, BorderLayout.CENTER);
627 if (bindingSelector.areStaticValuesAllowed() || bindingSelector.areCompoundBindingAllowed()) {
628 middlePaneWithOptions.add(optionsPanel, BorderLayout.SOUTH);
629 }
630
631 add(middlePaneWithOptions, BorderLayout.CENTER);
632 add(_controlPanel, BorderLayout.SOUTH);
633
634 resetMethodCallPanel();
635
636
637 editStaticValue = true;
638 setEditStaticValue(false);
639
640 update();
641 FilteredJList<?> firstList = listAtIndex(0);
642 if (firstList != null && firstList.getModel().getSize() == 1) {
643 firstList.setSelectedIndex(0);
644 }
645
646
647 }
648
649
650
651
652
653
654
655
656
657
658 protected void updateSearchedTypeLabel() {
659 searchedTypeLabel.setText("[" + getTypeStringRepresentation() + "]");
660 }
661
662 private String getTypeStringRepresentation() {
663 if (bindingSelector.getEditedObject() == null || bindingSelector.getEditedObject().getDeclaredType() == null) {
664 return FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey("no_type");
665 }
666 else {
667 return TypeUtils.simpleRepresentation(bindingSelector.getEditedObject().getDeclaredType());
668 }
669 }
670
671 protected int getVisibleColsCount() {
672 return _lists.size();
673 }
674
675 public boolean ensureBindingValueExists() {
676 if (bindingSelector.getEditedObject() == null) {
677 return false;
678 }
679 if (bindingSelector.getEditedObject().getExpression() == null) {
680 bindingSelector.getEditedObject().setExpression(bindingSelector.makeBinding());
681 bindingSelector.fireEditedObjectChanged();
682 }
683 return true;
684 }
685
686 protected class FilteredJList<T> extends JList<T> {
687 public FilteredJList() {
688 super(new EmptyColumnListModel());
689 }
690
691 public String getFilter() {
692 return getModel().getFilter();
693 }
694
695 public void setFilter(String aFilter) {
696 getModel().setFilter(aFilter);
697 }
698
699 public boolean isFiltered() {
700 return StringUtils.isNotEmpty(getFilter());
701 }
702
703 @Override
704 public void setModel(ListModel<T> model) {
705 if (model != null && !(model instanceof BindingColumnListModel)) {
706 new Exception("Oops, this model is " + model).printStackTrace();
707 }
708 setFilter(null);
709 if (model != null) {
710 super.setModel(model);
711 }
712 }
713
714 @Override
715 public BindingColumnListModel getModel() {
716 if (super.getModel() instanceof BindingColumnListModel) {
717 return (BindingColumnListModel) super.getModel();
718 }
719 new Exception("Oops, got a " + super.getModel()).printStackTrace();
720 return null;
721 }
722 }
723
724 protected JList<String> makeNewJList() {
725 FilteredJList<String> newList = new FilteredJList<>();
726
727 TypeResolver typeResolver = new TypeResolver(newList);
728
729 newList.addMouseMotionListener(typeResolver);
730 newList.addMouseListener(typeResolver);
731
732 _lists.add(newList);
733 if (LOGGER.isLoggable(Level.FINE)) {
734 LOGGER.fine("makeNewJList() size = " + _lists.size());
735 }
736 newList.setPrototypeCellValue("123456789012345");
737 newList.setSize(new Dimension(100, 150));
738
739
740 newList.setCellRenderer(new BindingSelectorCellRenderer());
741 newList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
742 newList.addListSelectionListener(this);
743 newList.addMouseListener(new MouseAdapter() {
744 @Override
745 public void mouseClicked(MouseEvent e) {
746 if (e.getClickCount() == 2) {
747 if (bindingSelector.getEditedObject() != null && bindingSelector.getEditedObject().isValid()) {
748 bindingSelector.apply();
749 }
750 }
751 else if (e.getClickCount() == 1) {
752
753 JList<?> list = (JList<?>) e.getSource();
754 int index = _lists.indexOf(list);
755 if (LOGGER.isLoggable(Level.FINE)) {
756 LOGGER.fine("Click on index " + index);
757 }
758 if (index < 0) {
759 return;
760 }
761 _selectedPathElementIndex = index;
762 updateMethodCallPanel();
763 }
764 }
765 });
766
767 newList.addKeyListener(new KeyAdapter() {
768 @Override
769 public void keyTyped(KeyEvent e) {
770
771 }
772
773 @Override
774 public void keyPressed(KeyEvent e) {
775 if (e.getKeyChar() == '\n') {
776 bindingSelector._selectorPanel.processEnterPressed();
777 e.consume();
778 }
779 else if (e.getKeyChar() == KeyEvent.VK_BACK_SPACE) {
780 bindingSelector._selectorPanel.processBackspace();
781 e.consume();
782 }
783 else if (e.getKeyChar() == KeyEvent.VK_DELETE) {
784 bindingSelector._selectorPanel.processDelete();
785 e.consume();
786 }
787 else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
788 if (!ensureBindingValueExists()) {
789 return;
790 }
791 DataBinding<?> dataBinding = bindingSelector.getEditedObject();
792 if (dataBinding.isBindingValue()) {
793 int i = _lists.indexOf(e.getSource());
794 if (i > -1 && i < _lists.size() && listAtIndex(i + 1) != null
795 && listAtIndex(i + 1).getModel().getElementAt(0) != null
796 && listAtIndex(i + 1).getModel().getElementAt(0).getElement() instanceof BindingPathElement) {
797 ((BindingValue) dataBinding.getExpression()).setBindingPathElementAtIndex(
798 (BindingPathElement) listAtIndex(i + 1).getModel().getElementAt(0).getElement(), i);
799 bindingSelector.setEditedObject(dataBinding);
800 bindingSelector.fireEditedObjectChanged();
801 listAtIndex(i + 1).requestFocusInWindow();
802 }
803 e.consume();
804 }
805 }
806 else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
807 if (!ensureBindingValueExists()) {
808 return;
809 }
810 DataBinding<?> dataBinding = bindingSelector.getEditedObject();
811 if (dataBinding.isBindingValue()) {
812 int i = _lists.indexOf(e.getSource()) - 1;
813 if (((BindingValue) dataBinding.getExpression()).getBindingPath().size() > i && i > -1 && i < _lists.size()) {
814 ((BindingValue) dataBinding.getExpression()).removeBindingPathAt(i);
815
816
817 bindingSelector.setEditedObject(dataBinding);
818 bindingSelector.fireEditedObjectChanged();
819 listAtIndex(i).requestFocusInWindow();
820 }
821 e.consume();
822 }
823 }
824 }
825
826 });
827
828 browserPanel.add(
829 new JScrollPane(newList, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
830 newList.setVisibleRowCount(6);
831 revalidate();
832 repaint();
833 return newList;
834 }
835
836 int _selectedPathElementIndex = -1;
837
838 protected void resetMethodCallPanel() {
839 if (bindingSelector.getEditedObject() == null || bindingSelector.getEditedObject().isConstant()
840 || bindingSelector.getEditedObject().isBindingValue()
841 && ((BindingValue) bindingSelector.getEditedObject().getExpression()).getBindingPath().size() == 0) {
842 _selectedPathElementIndex = -1;
843 }
844 else if (bindingSelector.getEditedObject().isBindingValue()) {
845 _selectedPathElementIndex = ((BindingValue) bindingSelector.getEditedObject().getExpression()).getBindingPath().size();
846 }
847 updateMethodCallPanel();
848 }
849
850 void updateMethodCallPanel() {
851 if (LOGGER.isLoggable(Level.FINE)) {
852 LOGGER.fine("updateMethodCallPanel with " + bindingSelector.editionMode + " binding=" + bindingSelector.getEditedObject()
853 + " _selectedPathElementIndex=" + _selectedPathElementIndex);
854 }
855 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING && bindingSelector.getEditedObject().isBindingValue()) {
856 if (((BindingValue) bindingSelector.getEditedObject().getExpression()).isCompoundBinding() && _selectedPathElementIndex == -1) {
857 _selectedPathElementIndex = ((BindingValue) bindingSelector.getEditedObject().getExpression()).getBindingPathElementCount();
858 }
859 if (_selectedPathElementIndex >= _lists.size()) {
860 _selectedPathElementIndex = -1;
861 }
862 BindingValue bindingValue = (BindingValue) bindingSelector.getEditedObject().getExpression();
863 if (bindingValue == null) {
864 _selectedPathElementIndex = -1;
865 }
866 else if (_selectedPathElementIndex > bindingValue.getBindingPath().size()) {
867 _selectedPathElementIndex = -1;
868 }
869 if (_selectedPathElementIndex > -1 && bindingValue != null) {
870 JList<?> list = _lists.get(_selectedPathElementIndex);
871 int newSelectedIndex = list.getSelectedIndex();
872 if (newSelectedIndex > 0) {
873 BindingColumnElement selectedValue = (BindingColumnElement) list.getSelectedValue();
874 if (selectedValue.getElement() instanceof FunctionPathElement) {
875 BindingPathElement currentElement = bindingValue.getBindingPathElementAtIndex(_selectedPathElementIndex - 1);
876 if (currentElement instanceof FunctionPathElement && ((FunctionPathElement) currentElement).getFunction() != null
877 && ((FunctionPathElement) currentElement).getFunction()
878 .equals(((FunctionPathElement) selectedValue.getElement()).getFunction())) {
879 getMethodCallBindingsModel().setModel((FunctionPathElement) currentElement);
880 return;
881 }
882 }
883 }
884 }
885 getMethodCallBindingsModel().setModel(null);
886 return;
887 }
888 }
889
890 protected void deleteJList(JList<?> list) {
891 _lists.remove(list);
892 Component[] scrollPanes = browserPanel.getComponents();
893 for (int i = 0; i < scrollPanes.length; i++) {
894 if (((Container) scrollPanes[i]).isAncestorOf(list)) {
895 browserPanel.remove(scrollPanes[i]);
896 }
897 }
898 if (LOGGER.isLoggable(Level.FINE)) {
899 LOGGER.fine("deleteJList() size = " + _lists.size());
900 }
901 revalidate();
902 repaint();
903 }
904
905 protected FilteredJList<?> listAtIndex(int index) {
906 if (index >= 0 && index < _lists.size()) {
907 return _lists.elementAt(index);
908 }
909 return null;
910 }
911
912
913
914
915
916
917
918
919
920 @Override
921 protected void fireBindableChanged() {
922 _rootBindingColumnListModel = buildRootColumnListModel();
923 update();
924 }
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940 private void clearColumns() {
941 listAtIndex(0).setModel(getRootColumnListModel());
942 int lastUpdatedList = 0;
943
944 int lastVisibleList = defaultVisibleColCount - 1;
945 if (lastUpdatedList > lastVisibleList) {
946 lastVisibleList = lastUpdatedList;
947 }
948 int currentSize = getVisibleColsCount();
949 for (int i = lastVisibleList + 1; i < currentSize; i++) {
950 JList<?> toRemove = listAtIndex(getVisibleColsCount() - 1);
951 deleteJList(toRemove);
952 }
953
954 for (int i = lastUpdatedList + 1; i < getVisibleColsCount(); i++) {
955 JList<?> list = listAtIndex(i);
956 list.setModel(EMPTY_MODEL);
957 }
958 }
959
960 @Override
961 protected void update() {
962 DataBinding<?> binding = bindingSelector.getEditedObject();
963 if (LOGGER.isLoggable(Level.FINE)) {
964 LOGGER.fine("update with " + binding);
965 }
966
967
968
969 if (binding == null || binding.isConstant() || binding.isUnset()) {
970 clearColumns();
971 if (binding == null) {
972 setEditStaticValue(false);
973 }
974 }
975 else if (binding.isBindingValue()) {
976 BindingValue bindingValue = (BindingValue) binding.getExpression();
977 listAtIndex(0).setModel(getRootColumnListModel());
978 int lastUpdatedList = 0;
979
980
981
982 if (bindingValue.getBindingVariable() != null) {
983 if (bindingValue.getBindingVariable().getType() != null) {
984 listAtIndex(1)
985 .setModel(getColumnListModel(bindingValue.getBindingVariable(), bindingValue.getBindingVariable().getType()));
986 }
987 else {
988 listAtIndex(1).setModel(EMPTY_MODEL);
989 }
990 listAtIndex(0).removeListSelectionListener(this);
991 BindingColumnElement elementToSelect = listAtIndex(0).getModel().getElementFor(bindingValue.getBindingVariable());
992
993 listAtIndex(0).setSelectedValue(elementToSelect, true);
994 listAtIndex(0).addListSelectionListener(this);
995 lastUpdatedList = 1;
996
997 for (int i = 0; i < bindingValue.getBindingPath().size(); i++) {
998 BindingPathElement pathElement = bindingValue.getBindingPath().get(i);
999 if (i + 2 == getVisibleColsCount()) {
1000 final JList<?> l = makeNewJList();
1001 SwingUtilities.invokeLater(new Runnable() {
1002 @Override
1003 public void run() {
1004 Rectangle r = SwingUtilities.convertRectangle(l, l.getBounds(), browserPanel);
1005
1006 browserPanel.scrollRectToVisible(r);
1007 }
1008 });
1009 }
1010
1011
1012
1013
1014
1015
1016 Type resultingType = bindingValue.getBindingPath().get(i).getType();
1017 listAtIndex(i + 2).setModel(getColumnListModel(bindingValue.getBindingPath().get(i), resultingType));
1018 lastUpdatedList = i + 2;
1019
1020 listAtIndex(i + 1).removeListSelectionListener(this);
1021
1022 BindingColumnElement theElementToSelect = listAtIndex(i + 1).getModel().getElementFor(pathElement);
1023 listAtIndex(i + 1).setSelectedValue(theElementToSelect, true);
1024
1025 listAtIndex(i + 1).addListSelectionListener(this);
1026 if (i < bindingValue.getBindingPath().size() - 1) {
1027 listAtIndex(i).setFilter(null);
1028 }
1029 }
1030
1031 }
1032
1033
1034 cleanLists(lastUpdatedList);
1035
1036 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING ) {
1037
1038
1039 updateMethodCallPanel();
1040 }
1041
1042
1043
1044
1045 }
1046
1047 updateSearchedTypeLabel();
1048
1049 if (binding != null) {
1050 if (LOGGER.isLoggable(Level.FINE)) {
1051 LOGGER.fine("Binding " + binding + " isValid()=" + binding.isValid());
1052 }
1053 else if (LOGGER.isLoggable(Level.FINE)) {
1054 LOGGER.fine("Binding is null");
1055 }
1056 }
1057
1058 updateStatus(binding);
1059 }
1060
1061 @Override
1062 protected void updateStatus(DataBinding<?> binding) {
1063
1064 connectButton.setEnabled(binding != null && binding.isValid());
1065
1066
1067
1068
1069 if (binding != null && binding.isValid()) {
1070 if (ToolBox.isMacOSLaf()) {
1071 connectButton.setSelected(true);
1072 }
1073 }
1074 if (binding != null) {
1075 bindingSelector.getTextField().setForeground(binding.isValid() ? Color.BLACK : Color.RED);
1076 bindingSelector.getTextField().setSelectedTextColor(binding.isValid() ? Color.BLACK : Color.RED);
1077
1078 if (bindingSelector.areStaticValuesAllowed() && staticBindingPanel != null) {
1079 staticBindingPanel.updateConstantValuePanel();
1080 }
1081
1082 if (binding.isBindingValue()) {
1083 setEditStaticValue(false);
1084 }
1085 else if (binding.isConstant()) {
1086 setEditStaticValue(true);
1087 }
1088 }
1089 }
1090
1091 private void cleanLists(int lastUpdatedList) {
1092
1093 int lastVisibleList = defaultVisibleColCount - 1;
1094 if (lastUpdatedList > lastVisibleList) {
1095 lastVisibleList = lastUpdatedList;
1096 }
1097 int currentSize = getVisibleColsCount();
1098 for (int i = lastVisibleList + 1; i < currentSize; i++) {
1099 JList<?> toRemove = listAtIndex(getVisibleColsCount() - 1);
1100 deleteJList(toRemove);
1101 }
1102
1103 for (int i = lastUpdatedList + 1; i < getVisibleColsCount(); i++) {
1104 JList<?> list = listAtIndex(i);
1105 list.setModel(EMPTY_MODEL);
1106 }
1107
1108 }
1109
1110 private boolean editStaticValue;
1111
1112 boolean getEditStaticValue() {
1113 return editStaticValue;
1114 }
1115
1116 void setEditStaticValue(boolean aFlag) {
1117 if (!bindingSelector.areStaticValuesAllowed() || staticBindingPanel == null) {
1118 return;
1119 }
1120 if (editStaticValue != aFlag) {
1121 editStaticValue = aFlag;
1122 if (editStaticValue) {
1123 staticBindingPanel.enableStaticBindingPanel();
1124 for (int i = 0; i < getVisibleColsCount(); i++) {
1125 listAtIndex(i).setEnabled(false);
1126 }
1127 }
1128 else {
1129 staticBindingPanel.disableStaticBindingPanel();
1130
1131 for (int i = 0; i < getVisibleColsCount(); i++) {
1132 listAtIndex(i).setEnabled(true);
1133 }
1134
1135 _rootBindingColumnListModel = buildRootColumnListModel();
1136
1137
1138 listAtIndex(0).setModel(getRootColumnListModel());
1139
1140 }
1141 staticBindingPanel.updateConstantValuePanel();
1142 }
1143 }
1144
1145 private boolean editTranstypedBinding;
1146
1147 boolean getEditTranstypedBinding() {
1148 return editTranstypedBinding;
1149 }
1150
1151 protected void updateListModels() {
1152 _rootBindingColumnListModel = buildRootColumnListModel();
1153
1154 for (Hashtable<Type, BindingColumnListModel> h : _listModels.values()) {
1155 for (BindingColumnListModel columnListModel : h.values()) {
1156 columnListModel.updateListModel();
1157 }
1158 }
1159 }
1160
1161 protected BindingColumnListModel getRootColumnListModel() {
1162 if (_rootBindingColumnListModel == null) {
1163 _rootBindingColumnListModel = buildRootColumnListModel();
1164 }
1165 return _rootBindingColumnListModel;
1166 }
1167
1168 protected BindingColumnListModel buildRootColumnListModel() {
1169 if (bindingSelector.getBindingModel() != null) {
1170 if (LOGGER.isLoggable(Level.FINE)) {
1171 LOGGER.fine("buildRootColumnListModel() from " + bindingSelector.getBindingModel());
1172 }
1173 return new RootBindingColumnListModel(bindingSelector.getBindingModel());
1174 }
1175 if (LOGGER.isLoggable(Level.FINE)) {
1176 LOGGER.fine("buildRootColumnListModel(): EMPTY_MODEL");
1177 }
1178 return EMPTY_MODEL;
1179 }
1180
1181
1182
1183
1184
1185
1186 protected BindingColumnListModel getColumnListModel(IBindingPathElement element, Type resultingType) {
1187 if (element == null) {
1188 return EMPTY_MODEL;
1189 }
1190 if (resultingType == null) {
1191 return EMPTY_MODEL;
1192 }
1193
1194 Hashtable<Type, BindingColumnListModel> h = _listModels.get(element);
1195 if (h == null) {
1196 h = new Hashtable<>();
1197 _listModels.put(element, h);
1198 }
1199 BindingColumnListModel returned = h.get(resultingType);
1200 if (returned == null) {
1201 returned = makeColumnListModel(element, resultingType);
1202 h.put(resultingType, returned);
1203 }
1204 return returned;
1205
1206
1207
1208 }
1209
1210 protected BindingColumnListModel makeColumnListModel(IBindingPathElement element, Type resultingType) {
1211 return new NormalBindingColumnListModel(element, resultingType);
1212 }
1213
1214 protected class BindingColumnElement {
1215 private IBindingPathElement _element;
1216 private Type _resultingType;
1217
1218 protected BindingColumnElement(IBindingPathElement element, Type resultingType) {
1219 _element = element;
1220 _resultingType = resultingType;
1221 if (resultingType == null) {
1222 LOGGER.warning("make BindingColumnElement with null type !");
1223 }
1224 }
1225
1226 private void delete() {
1227 _element = null;
1228 _resultingType = null;
1229 }
1230
1231 public IBindingPathElement getElement() {
1232 return _element;
1233 }
1234
1235
1236 public Type getResultingType() {
1237 return _resultingType;
1238 }
1239
1240 public String getLabel() {
1241 return getElement().getLabel();
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254 }
1255
1256 public String getTypeStringRepresentation() {
1257 if (getResultingType() == null) {
1258 return FIBModelObjectImpl.GINA_LOCALIZATION.localizedForKey("no_type");
1259 }
1260 return TypeUtils.simpleRepresentation(getResultingType());
1261 }
1262
1263 public String getTooltipText() {
1264 return getElement().getTooltipText(getResultingType());
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 }
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332 @Override
1333 public String toString() {
1334 return "BindingColumnElement/" + getLabel() + "[" + _element.toString() + "]";
1335 }
1336
1337 @Override
1338 public int hashCode() {
1339 return (_element == null ? 0 : _element.hashCode()) + (_resultingType == null ? 0 : _resultingType.hashCode());
1340 }
1341
1342 @Override
1343 public boolean equals(Object obj) {
1344 if (obj instanceof BindingColumnElement) {
1345 BindingColumnElement bce = (BindingColumnElement) obj;
1346 if (_element == null) {
1347 return false;
1348 }
1349 if (_resultingType == null) {
1350 return false;
1351 }
1352 return _element.equals(bce._element) && _resultingType.equals(bce._resultingType);
1353 }
1354 return super.equals(obj);
1355 }
1356
1357 }
1358
1359 abstract class BindingColumnListModel extends AbstractListModel implements PropertyChangeListener {
1360 public void fireModelChanged() {
1361 fireContentsChanged(this, 0, getUnfilteredSize() - 1);
1362 }
1363
1364 public BindingColumnElement getElementFor(IBindingPathElement element) {
1365
1366
1367
1368
1369 for (int i = 0; i < getSize(); i++) {
1370
1371 if (getElementAt(i).getElement().equals(element)) {
1372 return getElementAt(i);
1373 }
1374 if (element instanceof FunctionPathElement && getElementAt(i).getElement() instanceof FunctionPathElement) {
1375
1376 FunctionPathElement f1 = (FunctionPathElement) element;
1377 FunctionPathElement f2 = (FunctionPathElement) getElementAt(i).getElement();
1378 if (f1.getFunction() != null && f1.getFunction().equals(f2.getFunction())) {
1379
1380 return getElementAt(i);
1381 }
1382
1383 }
1384 }
1385 LOGGER.info("I cannot find " + element + " of " + (element != null ? element.getClass() : null));
1386
1387
1388
1389
1390
1391 return null;
1392 }
1393
1394 @Override
1395 public void propertyChange(PropertyChangeEvent evt) {
1396
1397 }
1398
1399 public void updateListModel() {
1400
1401 }
1402
1403 public void delete() {
1404
1405 }
1406
1407 private String filter = null;
1408
1409 public String getFilter() {
1410 return filter;
1411 }
1412
1413 public void setFilter(String aFilter) {
1414 filter = aFilter;
1415 fireModelChanged();
1416 }
1417
1418 @Override
1419 public int getSize() {
1420 if (getFilter() == null && !bindingSelector._hideFilteredObjects) {
1421 return getUnfilteredSize();
1422 }
1423 int returned = 0;
1424 if (!bindingSelector._hideFilteredObjects) {
1425 for (int i = 0; i < getUnfilteredSize(); i++) {
1426 if (getUnfilteredElementAt(i).getLabel().startsWith(filter)) {
1427 returned++;
1428 }
1429 }
1430 }
1431 else if (getFilter() == null) {
1432 for (int i = 0; i < getUnfilteredSize(); i++) {
1433 if (!isFiltered(getUnfilteredElementAt(i))) {
1434 returned++;
1435 }
1436 }
1437 }
1438 else {
1439 for (int i = 0; i < getUnfilteredSize(); i++) {
1440 if (getUnfilteredElementAt(i).getLabel().startsWith(filter) && !isFiltered(getUnfilteredElementAt(i))) {
1441 returned++;
1442 }
1443 }
1444 }
1445 return returned;
1446 }
1447
1448 @Override
1449 public BindingColumnElement getElementAt(int index) {
1450 if (getFilter() == null && !bindingSelector._hideFilteredObjects) {
1451 return getUnfilteredElementAt(index);
1452 }
1453 if (!bindingSelector._hideFilteredObjects) {
1454 int searchedIndex = -1;
1455 for (int i = 0; i < getUnfilteredSize(); i++) {
1456 if (getUnfilteredElementAt(i).getLabel().startsWith(filter)) {
1457 searchedIndex++;
1458 }
1459 if (searchedIndex == index) {
1460 return getUnfilteredElementAt(i);
1461 }
1462 }
1463 }
1464 else if (getFilter() == null) {
1465 int searchedIndex = -1;
1466 for (int i = 0; i < getUnfilteredSize(); i++) {
1467 if (!isFiltered(getUnfilteredElementAt(i))) {
1468 searchedIndex++;
1469 }
1470 if (searchedIndex == index) {
1471 return getUnfilteredElementAt(i);
1472 }
1473 }
1474 }
1475 else {
1476 int searchedIndex = -1;
1477 for (int i = 0; i < getUnfilteredSize(); i++) {
1478 if (getUnfilteredElementAt(i).getLabel().startsWith(filter) && !isFiltered(getUnfilteredElementAt(i))) {
1479 searchedIndex++;
1480 }
1481 if (searchedIndex == index) {
1482 return getUnfilteredElementAt(i);
1483 }
1484 }
1485 }
1486 return null;
1487 }
1488
1489 private boolean isFiltered(BindingColumnElement columnElement) {
1490
1491
1492
1493 columnElement.getResultingType();
1494
1495 if (columnElement.getElement() != null && columnElement.getElement() instanceof BindingVariable) {
1496 BindingVariable bv = (BindingVariable) columnElement.getElement();
1497 if (bv.getType() == null) {
1498 return true;
1499 }
1500 }
1501 else if (columnElement.getElement() != null) {
1502 DataBinding<?> binding = bindingSelector.getEditedObject();
1503 if (binding != null && binding.isBindingValue()) {
1504 BindingValue bindingValue = (BindingValue) binding.getExpression();
1505 if (bindingValue.isValid()
1506 && bindingValue.isLastBindingPathElement(columnElement.getElement())
1507 && bindingSelector.isConnected()) {
1508
1509 }
1510 else if (columnElement.getResultingType() != null) {
1511 if (TypeUtils.isResolved(columnElement.getResultingType()) && bindingSelector.getBindable() != null) {
1512
1513 if (bindingSelector.getBindable().getBindingFactory()
1514 .getAccessibleSimplePathElements(columnElement.getElement()).size() > 0) {}
1515 else {
1516 if (!TypeUtils.isTypeAssignableFrom(binding.getDeclaredType(), columnElement.getResultingType(), true)) {
1517 return true;
1518 }
1519 if (binding.isSettable() && !columnElement.getElement().isSettable()) {
1520 return true;
1521 }
1522 }
1523 }
1524 }
1525 }
1526 }
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595 return false;
1596 }
1597
1598 public abstract int getUnfilteredSize();
1599
1600 public abstract BindingColumnElement getUnfilteredElementAt(int index);
1601
1602 }
1603
1604 private class NormalBindingColumnListModel extends BindingColumnListModel {
1605 private final Type _type;
1606 private final IBindingPathElement _element;
1607 private final Vector<BindingPathElement> _accessibleProperties;
1608 private final Vector<BindingPathElement> _accessibleMethods;
1609 private final Vector<BindingColumnElement> _elements;
1610
1611 NormalBindingColumnListModel(IBindingPathElement element, Type resultingType) {
1612 super();
1613 _element = element;
1614 _type = resultingType;
1615 if (LOGGER.isLoggable(Level.FINE)) {
1616 LOGGER.fine("Build NormalBindingColumnListModel for " + element + " base class=" + TypeUtils.getBaseClass(_type));
1617 }
1618 _accessibleProperties = new Vector<>();
1619 _accessibleMethods = new Vector<>();
1620 _elements = new Vector<>();
1621 updatePathElements();
1622 if (element instanceof HasPropertyChangeSupport && ((HasPropertyChangeSupport) element).getPropertyChangeSupport() != null) {
1623 ((HasPropertyChangeSupport) element).getPropertyChangeSupport().addPropertyChangeListener(this);
1624 }
1625 }
1626
1627 @Override
1628 public void delete() {
1629 if (_element instanceof HasPropertyChangeSupport && ((HasPropertyChangeSupport) _element).getPropertyChangeSupport() != null) {
1630 ((HasPropertyChangeSupport) _element).getPropertyChangeSupport().removePropertyChangeListener(this);
1631 }
1632 super.delete();
1633 }
1634
1635 @Override
1636 public void propertyChange(PropertyChangeEvent evt) {
1637 super.propertyChange(evt);
1638 if (evt.getPropertyName().equals(BindingPathElement.BINDING_PATH_CHANGED)) {
1639 updatePathElements();
1640 }
1641 }
1642
1643 @Override
1644 public void updateListModel() {
1645 super.updateListModel();
1646 updatePathElements();
1647 }
1648
1649 private void updatePathElements() {
1650
1651 _accessibleProperties.clear();
1652 _accessibleMethods.clear();
1653
1654 if (bindingSelector.getBindable() == null) {
1655 return;
1656 }
1657
1658 _elements.clear();
1659
1660 if (TypeUtils.getBaseClass(_type) == null) {
1661 return;
1662 }
1663
1664 Bindable bdable = bindingSelector.getBindable();
1665 if (bdable != null) {
1666 BindingFactory bf = bdable.getBindingFactory();
1667 if (bf != null) {
1668 _accessibleProperties.addAll(bf.getAccessibleSimplePathElements(_element));
1669
1670 if (bindingSelector.editionMode == EditionMode.COMPOUND_BINDING) {
1671 _accessibleProperties
1672 .addAll(bindingSelector.getBindable().getBindingFactory().getAccessibleFunctionPathElements(_element));
1673 }
1674
1675 for (BindingPathElement p : _accessibleProperties) {
1676 _elements.add(new BindingColumnElement(p, TypeUtils.makeInstantiatedType(p.getType(), _type)));
1677 }
1678 for (BindingPathElement m : _accessibleMethods) {
1679 _elements.add(new BindingColumnElement(m, TypeUtils.makeInstantiatedType(m.getType(), _type)));
1680 }
1681 }
1682 }
1683 }
1684
1685 @Override
1686 public int getUnfilteredSize() {
1687 return _elements.size();
1688 }
1689
1690 @Override
1691 public BindingColumnElement getUnfilteredElementAt(int index) {
1692 if (index < _elements.size() && index >= 0) {
1693 return _elements.elementAt(index);
1694 }
1695 return null;
1696 }
1697
1698
1699
1700
1701
1702 }
1703
1704 class EmptyColumnListModel extends BindingColumnListModel {
1705 @Override
1706 public int getUnfilteredSize() {
1707 return 0;
1708 }
1709
1710 @Override
1711 public BindingColumnElement getUnfilteredElementAt(int index) {
1712 return null;
1713 }
1714
1715 }
1716
1717 private class RootBindingColumnListModel extends BindingColumnListModel {
1718 private final BindingModel _myBindingModel;
1719 private final Vector<BindingColumnElement> _elements;
1720
1721 RootBindingColumnListModel(BindingModel bindingModel) {
1722 super();
1723 _myBindingModel = bindingModel;
1724 _elements = new Vector<>();
1725 bindingModel.getPropertyChangeSupport().addPropertyChangeListener(this);
1726 updateBindingVariables();
1727 }
1728
1729 @Override
1730 public void propertyChange(PropertyChangeEvent evt) {
1731 super.propertyChange(evt);
1732 if (evt.getSource() == _myBindingModel) {
1733 updateBindingVariables();
1734 }
1735 else if (evt.getSource() instanceof BindingVariable) {
1736
1737 evt.getSource();
1738
1739 }
1740 }
1741
1742 @Override
1743 public void updateListModel() {
1744 super.updateListModel();
1745 updateBindingVariables();
1746 }
1747
1748 private final List<BindingVariable> observedBindingVariables = new ArrayList<>();
1749
1750 private void updateBindingVariables() {
1751
1752 if (LOGGER.isLoggable(Level.FINE)) {
1753 LOGGER.fine("BindingModel is: " + _myBindingModel + " with " + _myBindingModel.getBindingVariablesCount());
1754 }
1755 for (BindingVariable bv : observedBindingVariables) {
1756 if (bv.getPropertyChangeSupport() != null) {
1757 bv.getPropertyChangeSupport().removePropertyChangeListener(this);
1758 }
1759 }
1760 for (BindingColumnElement e : _elements) {
1761 e.delete();
1762 }
1763 _elements.clear();
1764 for (int i = 0; i < _myBindingModel.getBindingVariablesCount(); i++) {
1765 BindingVariable bv = _myBindingModel.getBindingVariableAt(i);
1766 _elements.add(new BindingColumnElement(bv, bv.getType()));
1767 if (bv.getPropertyChangeSupport() != null) {
1768 bv.getPropertyChangeSupport().addPropertyChangeListener(this);
1769 }
1770 }
1771 }
1772
1773 @Override
1774 public int getUnfilteredSize() {
1775 return _elements.size();
1776 }
1777
1778 @Override
1779 public BindingColumnElement getUnfilteredElementAt(int index) {
1780 return _elements.elementAt(index);
1781 }
1782
1783 @Override
1784 public String toString() {
1785 return "RootBindingColumnListModel with " + getSize() + " elements";
1786 }
1787
1788 }
1789
1790 protected class TypeResolver extends MouseAdapter {
1791
1792 private final JList<?> list;
1793
1794 protected TypeResolver(JList<?> aList) {
1795 currentFocused = null;
1796 list = aList;
1797 }
1798
1799 @Override
1800 public void mouseMoved(MouseEvent e) {
1801 displayLabel(e);
1802 }
1803
1804 @Override
1805 public void mouseClicked(MouseEvent e) {
1806 displayLabel(e);
1807 }
1808
1809 private void displayLabel(MouseEvent e) {
1810
1811
1812 int index = list.locationToIndex(e.getPoint());
1813
1814
1815 if (index < 0 || index >= list.getModel().getSize()) {
1816 return;
1817 }
1818 BindingColumnElement item = ((BindingColumnListModel) list.getModel()).getElementAt(index);
1819
1820 if (item != currentFocused) {
1821 currentFocused = item;
1822 currentTypeLabel.setText(currentFocused.getTypeStringRepresentation());
1823 }
1824 }
1825
1826 }
1827
1828 protected class BindingSelectorCellRenderer extends DefaultListCellRenderer {
1829
1830 private final JPanel panel;
1831 private final JLabel iconLabel;
1832
1833 public BindingSelectorCellRenderer() {
1834 panel = new JPanel(new BorderLayout());
1835 iconLabel = new JLabel();
1836 panel.add(iconLabel, BorderLayout.EAST);
1837 panel.add(this);
1838 }
1839
1840 @Override
1841 public Component getListCellRendererComponent(JList<?> list, Object bce, int index, boolean isSelected, boolean cellHasFocus) {
1842 JComponent returned = (JComponent) super.getListCellRendererComponent(list, bce, index, isSelected, cellHasFocus);
1843 if (returned instanceof JLabel) {
1844 JLabel label = (JLabel) returned;
1845 label.setToolTipText(null);
1846 iconLabel.setVisible(false);
1847
1848 if (bce instanceof BindingColumnElement) {
1849 BindingColumnElement columnElement = (BindingColumnElement) bce;
1850
1851
1852
1853 columnElement.getResultingType();
1854 label.setText(columnElement.getLabel());
1855
1856 returned = getIconLabelComponent(label, FIBIconLibrary.ARROW_RIGHT_ICON);
1857
1858 if (columnElement.getElement().getType() != null) {
1859 returned.setToolTipText(columnElement.getTooltipText());
1860 }
1861 else {
1862 label.setForeground(Color.GRAY);
1863 }
1864
1865 DataBinding<?> binding = bindingSelector.getEditedObject();
1866 if (binding != null && binding.isBindingValue()) {
1867 BindingValue bindingValue = (BindingValue) binding.getExpression();
1868
1869 if (bindingValue.isValid()
1870 && bindingValue.isLastBindingPathElement(columnElement.getElement())
1871 && bindingSelector.isConnected()) {
1872
1873 returned = getIconLabelComponent(label, FIBIconLibrary.CONNECTED_ICON);
1874 }
1875 else if (columnElement.getResultingType() != null) {
1876 if (TypeUtils.isResolved(columnElement.getResultingType()) && bindingSelector.getBindable() != null) {
1877
1878 if (bindingSelector.getBindable().getBindingFactory() != null
1879 && bindingSelector.getBindable().getBindingFactory()
1880 .getAccessibleSimplePathElements(columnElement.getElement()) != null
1881 && bindingSelector.getBindable().getBindingFactory()
1882 .getAccessibleSimplePathElements(columnElement.getElement()).size() > 0) {
1883 returned = getIconLabelComponent(label, FIBIconLibrary.ARROW_RIGHT_ICON);
1884 }
1885 else {
1886 if (!TypeUtils.isTypeAssignableFrom(binding.getDeclaredType(), columnElement.getResultingType(),
1887 true)) {
1888 label.setForeground(Color.GRAY);
1889 }
1890 if (binding.isSettable() && !columnElement.getElement().isSettable()) {
1891 label.setForeground(Color.GRAY);
1892 }
1893 }
1894 }
1895 }
1896 }
1897
1898 }
1899 else {
1900
1901
1902 }
1903
1904 }
1905 return returned;
1906 }
1907
1908 private JComponent getIconLabelComponent(JLabel label, Icon icon) {
1909 iconLabel.setVisible(true);
1910 iconLabel.setIcon(icon);
1911 iconLabel.setOpaque(label.isOpaque());
1912 iconLabel.setBackground(label.getBackground());
1913 panel.setToolTipText(label.getToolTipText());
1914 if (label.getParent() != panel) {
1915 panel.add(label);
1916 }
1917 return panel;
1918 }
1919 }
1920
1921 protected JPanel getControlPanel() {
1922 return _controlPanel;
1923 }
1924
1925 @Override
1926 public void valueChanged(ListSelectionEvent e) {
1927
1928 if (e.getValueIsAdjusting()) {
1929 return;
1930 }
1931
1932 DataBinding<?> dataBinding = bindingSelector.getEditedObject();
1933
1934 if (dataBinding == null) {
1935 LOGGER.warning("dataBinding should not be null");
1936 return;
1937 }
1938
1939 if (dataBinding.getExpression() == null) {
1940
1941 BindingValue newBindingValue = new BindingValue();
1942 newBindingValue.setBindingVariable(getSelectedBindingVariable());
1943 newBindingValue.setDataBinding(dataBinding);
1944
1945 dataBinding.setExpression(newBindingValue );
1946
1947
1948
1949
1950
1951
1952 }
1953
1954 JList<?> list = (JList<?>) e.getSource();
1955 int index = _lists.indexOf(list);
1956 _selectedPathElementIndex = index;
1957 if (index < 0) {
1958 return;
1959 }
1960 int newSelectedIndex = list.getSelectedIndex();
1961
1962 if (LOGGER.isLoggable(Level.FINE)) {
1963 LOGGER.fine("I select something from list at index " + index + " selected=" + newSelectedIndex);
1964 }
1965
1966 if (newSelectedIndex < 0) {
1967 return;
1968 }
1969
1970
1971 valueSelected(index, list);
1972
1973 list.removeListSelectionListener(this);
1974 list.setSelectedIndex(newSelectedIndex);
1975 list.addListSelectionListener(this);
1976
1977 }
1978
1979 private static boolean hasBindingPathForm(String textValue) {
1980 if (textValue.length() == 0) {
1981 return false;
1982 }
1983
1984 boolean startingPathItem = true;
1985 for (int i = 0; i < textValue.length(); i++) {
1986 char c = textValue.charAt(i);
1987 if (c == '.') {
1988 startingPathItem = true;
1989 }
1990 else {
1991 boolean isNormalChar = c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' && !startingPathItem;
1992 if (!isNormalChar) {
1993 return false;
1994 }
1995 startingPathItem = false;
1996 }
1997 }
1998 return true;
1999 }
2000
2001 @Override
2002 protected void synchronizePanelWithTextFieldValue(String textValue) {
2003 if (LOGGER.isLoggable(Level.FINE)) {
2004 LOGGER.fine("Request synchronizePanelWithTextFieldValue " + textValue);
2005 }
2006
2007 try {
2008 bindingSelector.isUpdatingModel = true;
2009
2010 if (!bindingSelector.popupIsShown() && textValue != null
2011 && !bindingSelector.isAcceptableAsBeginningOfStaticBindingValue(textValue)) {
2012 boolean requestFocus = bindingSelector.getTextField().hasFocus();
2013 bindingSelector.openPopup();
2014 if (requestFocus) {
2015 SwingUtilities.invokeLater(new Runnable() {
2016 @Override
2017 public void run() {
2018 bindingSelector.getTextField().requestFocusInWindow();
2019 }
2020 });
2021 }
2022 }
2023
2024 if (bindingSelector.getTextField().hasFocus()) {
2025 if (bindingSelector.getEditedObject() != null && bindingSelector.getEditedObject().isBindingValue()) {
2026
2027 }
2028 if (bindingSelector._selectorPanel != null) {
2029 filterWithCurrentInput(textValue);
2030 }
2031 }
2032
2033 if (textValue == null || !textValue.equals(bindingSelector.renderedString(bindingSelector.getEditedObject()))) {
2034 bindingSelector.getTextField().setForeground(Color.RED);
2035 }
2036 else {
2037 bindingSelector.getTextField().setForeground(Color.BLACK);
2038 }
2039
2040 } finally {
2041 bindingSelector.isUpdatingModel = false;
2042 }
2043
2044 }
2045
2046 private void filterWithCurrentInput(String textValue) {
2047 if (LOGGER.isLoggable(Level.FINE)) {
2048 LOGGER.fine("Try to filter for current input " + textValue);
2049 }
2050
2051 if (!hasBindingPathForm(textValue)) {
2052 return;
2053 }
2054
2055 StringTokenizer tokenizer = new StringTokenizer(textValue, ".", false);
2056 boolean isCurrentlyValid = true;
2057 int listIndex = 0;
2058 String element = null;
2059 while (isCurrentlyValid && tokenizer.hasMoreTokens()) {
2060 element = tokenizer.nextToken();
2061 BindingColumnElement col_element = findElementEquals(_lists.get(listIndex).getModel(), element);
2062 if (col_element == null) {
2063 isCurrentlyValid = false;
2064 }
2065 else {
2066 bindingSelector.setUpdatingModel(true);
2067 if (!ensureBindingValueExists()) {
2068 bindingSelector.setUpdatingModel(false);
2069 return;
2070 }
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085 _lists.get(listIndex).removeListSelectionListener(this);
2086 _lists.get(listIndex).setFilter(null);
2087 _lists.get(listIndex).setSelectedValue(col_element, true);
2088 _lists.get(listIndex).addListSelectionListener(this);
2089 valueSelected(listIndex, _lists.get(listIndex));
2090 bindingSelector.setUpdatingModel(false);
2091 listIndex++;
2092 }
2093 }
2094
2095 if (!isCurrentlyValid) {
2096 _lists.get(listIndex).setFilter(element);
2097 completionInfo = new CompletionInfo(_lists.get(listIndex), element, textValue);
2098 if (completionInfo.matchingElements.size() > 0) {
2099 BindingColumnElement col_element = completionInfo.matchingElements.firstElement();
2100 _lists.get(listIndex).removeListSelectionListener(this);
2101 _lists.get(listIndex).setSelectedValue(col_element, true);
2102 _lists.get(listIndex).addListSelectionListener(this);
2103 }
2104
2105 }
2106
2107 cleanLists(listIndex);
2108 }
2109
2110 private CompletionInfo completionInfo;
2111
2112 protected class CompletionInfo {
2113 String validPath = null;
2114 String completionInitPath = null;
2115 String commonBeginningPath = null;
2116 Vector<BindingColumnElement> matchingElements = null;
2117
2118 protected CompletionInfo(FilteredJList<?> list, String subPartialPath, String fullPath) {
2119 validPath = fullPath.substring(0, fullPath.lastIndexOf(".") + 1);
2120 completionInitPath = subPartialPath;
2121 matchingElements = findElementsMatching(list.getModel(), subPartialPath);
2122 if (matchingElements.size() == 1) {
2123 commonBeginningPath = matchingElements.firstElement().getLabel();
2124 }
2125 else if (matchingElements.size() > 1) {
2126 int endCommonPathIndex = 0;
2127 boolean foundDiff = false;
2128 while (!foundDiff) {
2129 if (endCommonPathIndex < matchingElements.firstElement().getLabel().length()) {
2130 char c = matchingElements.firstElement().getLabel().charAt(endCommonPathIndex);
2131 for (int i = 1; i < matchingElements.size(); i++) {
2132 String label = matchingElements.elementAt(i).getLabel();
2133 if (endCommonPathIndex < label.length() && label.charAt(endCommonPathIndex) != c) {
2134 foundDiff = true;
2135 }
2136 }
2137 if (!foundDiff) {
2138 endCommonPathIndex++;
2139 }
2140 }
2141 else {
2142 foundDiff = true;
2143 }
2144 }
2145 commonBeginningPath = matchingElements.firstElement().getLabel().substring(0, endCommonPathIndex);
2146 }
2147 }
2148
2149 @Override
2150 public String toString() {
2151 return "CompletionInfo, completionInitPath=" + completionInitPath + " validPath=" + validPath + " commonBeginningPath="
2152 + commonBeginningPath + " matchingElements=" + matchingElements;
2153 }
2154
2155 private boolean alreadyAutocompleted = false;
2156
2157 protected void autoComplete() {
2158 if (!alreadyAutocompleted) {
2159 bindingSelector.getTextField().setText(validPath + commonBeginningPath);
2160 }
2161 else {
2162 bindingSelector.getTextField().setText(validPath + commonBeginningPath + ".");
2163 }
2164 alreadyAutocompleted = true;
2165 SwingUtilities.invokeLater(new Runnable() {
2166 @Override
2167 public void run() {
2168 bindingSelector.getTextField().requestFocusInWindow();
2169 }
2170 });
2171 }
2172
2173 }
2174
2175 @Override
2176 protected void processEnterPressed() {
2177 LOGGER.fine("Pressed on ENTER");
2178
2179 int index = 0;
2180 if (bindingSelector.getEditedObject() != null) {
2181 index = StringUtils.countMatches(bindingSelector.getTextField().getText(), ".");
2182 }
2183
2184 FilteredJList<?> list = listAtIndex(index);
2185 if (list != null) {
2186 int currentSelected = list.getSelectedIndex();
2187 if (currentSelected > -1) {
2188 valueChanged(new ListSelectionEvent(list, currentSelected, currentSelected, false));
2189
2190 update();
2191 completionInfo = null;
2192 }
2193 }
2194
2195
2196
2197
2198 if (bindingSelector.getEditedObject() != null && bindingSelector.getEditedObject().isValid()) {
2199 bindingSelector.apply();
2200 }
2201 }
2202
2203 @Override
2204 protected void processDelete() {
2205 LOGGER.fine("Pressed on DELETE");
2206 suppressSelection();
2207 }
2208
2209 @Override
2210 protected void processBackspace() {
2211 LOGGER.fine("Pressed on BACKSPACE");
2212 if (!suppressSelection()) {
2213 if (bindingSelector.getTextField().getText().length() > 0) {
2214 bindingSelector.getTextField().setText(
2215 bindingSelector.getTextField().getText().substring(0, bindingSelector.getTextField().getText().length() - 1));
2216
2217 }
2218 }
2219 }
2220
2221 private boolean suppressSelection() {
2222 if (bindingSelector.getTextField().getText().length() > 0) {
2223 if (bindingSelector.getTextField().getSelectedText() != null && bindingSelector.getTextField().getSelectedText().length() > 0) {
2224 int begin = bindingSelector.getTextField().getSelectionStart();
2225 int end = bindingSelector.getTextField().getSelectionEnd();
2226 bindingSelector.getTextField().setText(bindingSelector.getTextField().getText().substring(0, begin)
2227 + bindingSelector.getTextField().getText().substring(end, bindingSelector.getTextField().getText().length()));
2228 return true;
2229 }
2230 }
2231 return false;
2232 }
2233
2234 @Override
2235 protected void processTabPressed() {
2236 LOGGER.fine("Pressed on TAB, completionInfo=" + completionInfo);
2237 if (completionInfo != null) {
2238
2239 completionInfo.autoComplete();
2240 }
2241 }
2242
2243 @Override
2244 protected void processUpPressed() {
2245 LOGGER.fine("Pressed on UP");
2246
2247 int index = 0;
2248 if (bindingSelector.getEditedObject() != null) {
2249 index = StringUtils.countMatches(bindingSelector.getTextField().getText(), ".");
2250 }
2251
2252 FilteredJList<?> list = listAtIndex(index);
2253
2254 int currentSelected = list.getSelectedIndex();
2255 if (currentSelected > 0) {
2256 list.removeListSelectionListener(this);
2257 list.setSelectedIndex(currentSelected - 1);
2258 list.addListSelectionListener(this);
2259 }
2260 }
2261
2262 @Override
2263 protected void processDownPressed() {
2264 LOGGER.fine("Pressed on DOWN");
2265 if (!bindingSelector.popupIsShown()) {
2266 bindingSelector.openPopup();
2267 }
2268
2269 int index = 0;
2270 if (bindingSelector.getEditedObject() != null) {
2271 index = StringUtils.countMatches(bindingSelector.getTextField().getText(), ".");
2272 }
2273
2274 FilteredJList<?> list = listAtIndex(index);
2275
2276 int currentSelected = list.getSelectedIndex();
2277 list.removeListSelectionListener(this);
2278 list.setSelectedIndex(currentSelected + 1);
2279 list.addListSelectionListener(this);
2280
2281 }
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315 boolean isKeyPathFromTextASubKeyPath(String inputText) {
2316 int dotCount = StringUtils.countMatches(inputText, ".");
2317 if (listAtIndex(dotCount) == null) {
2318 return false;
2319 }
2320 BindingColumnListModel listModel = listAtIndex(dotCount).getModel();
2321 String subPartialPath = inputText.substring(inputText.lastIndexOf(".") + 1);
2322 Vector<Integer> pathElementIndex = new Vector<>();
2323 ;
2324 BindingColumnElement pathElement = findElementMatching(listModel, subPartialPath, pathElementIndex);
2325 return pathElement != null;
2326 }
2327
2328 boolean isKeyPathFromPanelValid() {
2329 if (bindingSelector.getEditedObject() == null) {
2330 return false;
2331 }
2332 int i = 0;
2333 while (listAtIndex(i) != null && listAtIndex(i).getSelectedValue() != null) {
2334 i++;
2335 }
2336 if (listAtIndex(i - 1).getSelectedValue() instanceof BindingColumnElement) {
2337 if (TypeUtils.isTypeAssignableFrom(bindingSelector.getEditedObject().getDeclaredType(),
2338 ((BindingColumnElement) listAtIndex(i - 1).getSelectedValue()).getResultingType(), true)) {
2339 return true;
2340 }
2341 }
2342 return false;
2343 }
2344
2345 BindingValue makeBindingValueFromPanel() {
2346 if (bindingSelector.getEditedObject() == null || !bindingSelector.getEditedObject().isBindingValue()) {
2347 return null;
2348 }
2349 int i = 1;
2350 BindingColumnElement last = null;
2351 while (listAtIndex(i) != null && listAtIndex(i).getSelectedValue() != null) {
2352 last = (BindingColumnElement) listAtIndex(i).getSelectedValue();
2353
2354
2355 if (last.getElement() instanceof FunctionPathElement) {
2356 for (FunctionArgument arg : ((FunctionPathElement) last.getElement()).getArguments()) {
2357 DataBinding<?> argValue = ((FunctionPathElement) last.getElement()).getParameter(arg);
2358 if (argValue == null) {
2359 if (TypeUtils.isNumber(arg.getArgumentType())) {
2360 argValue = new DataBinding<>("0", bindingSelector.getBindable(), arg.getArgumentType(),
2361 BindingDefinitionType.GET);
2362 }
2363 else {
2364 argValue = new DataBinding<>("null", bindingSelector.getBindable(), arg.getArgumentType(),
2365 BindingDefinitionType.GET);
2366 }
2367 ((FunctionPathElement) last.getElement()).setParameter(arg, argValue);
2368 }
2369
2370 }
2371 }
2372
2373 ((BindingValue) bindingSelector.getEditedObject().getExpression())
2374 .setBindingPathElementAtIndex((BindingPathElement) last.getElement(), i - 1);
2375 i++;
2376 }
2377 if (last != null) {
2378 ((BindingValue) bindingSelector.getEditedObject().getExpression())
2379 .removeBindingPathElementAfter((BindingPathElement) last.getElement());
2380 }
2381 return (BindingValue) bindingSelector.getEditedObject().getExpression();
2382 }
2383
2384 protected void valueSelected(int index, JList<?> list) {
2385
2386 DataBinding<?> binding = bindingSelector.getEditedObject();
2387
2388
2389
2390 if (!binding.isBindingValue()) {
2391
2392 bindingSelector.editionMode = EditionMode.NORMAL_BINDING;
2393 binding.setExpression(bindingSelector.makeBinding());
2394
2395 if (!binding.isBindingValue()) {
2396 LOGGER.severe("Should never happen: valueSelected() called for a non-BindingValue instance !");
2397 return;
2398 }
2399 }
2400 BindingValue bindingValue = (BindingValue) binding.getExpression();
2401 if (LOGGER.isLoggable(Level.FINE)) {
2402 LOGGER.fine("Value selected: index=" + index + " list=" + list + " bindingValue=" + bindingValue);
2403 }
2404 BindingValueSelectorPanel.BindingColumnElement selectedValue = (BindingValueSelectorPanel.BindingColumnElement) list
2405 .getSelectedValue();
2406
2407
2408
2409
2410 if (selectedValue == null) {
2411 return;
2412 }
2413 if (index == 0 && selectedValue.getElement() instanceof BindingVariable) {
2414 if (list.getSelectedValue() != bindingValue.getBindingVariable()) {
2415 bindingSelector.disconnect();
2416 bindingValue.setBindingVariable((BindingVariable) selectedValue.getElement());
2417 binding.setExpression(bindingValue);
2418 bindingSelector.fireEditedObjectChanged();
2419 }
2420 }
2421 else {
2422 if (selectedValue.getElement() instanceof SimplePathElement) {
2423
2424 if (selectedValue.getElement() != bindingValue.getBindingPathElementAtIndex(index - 1)) {
2425 bindingSelector.disconnect();
2426 bindingValue.setBindingPathElementAtIndex((BindingPathElement) selectedValue.getElement(), index - 1);
2427 binding.setExpression(bindingValue);
2428 bindingSelector.fireEditedObjectChanged();
2429 }
2430 }
2431 else if (selectedValue.getElement() instanceof FunctionPathElement) {
2432
2433 BindingPathElement currentElement = bindingValue.getBindingPathElementAtIndex(index - 1);
2434
2435 LOGGER.info("Selecting currentElement " + currentElement + " selectedValue=" + selectedValue);
2436
2437 if (currentElement == null || !(currentElement instanceof FunctionPathElement)
2438 || ((FunctionPathElement) currentElement).getFunction() == null || !((FunctionPathElement) currentElement)
2439 .getFunction().equals(((FunctionPathElement) selectedValue.getElement()).getFunction())) {
2440 bindingSelector.disconnect();
2441 Function function = ((FunctionPathElement) selectedValue.getElement()).getFunction();
2442 LOGGER.info("Selecting function " + function);
2443 List<DataBinding<?>> args = new ArrayList<>();
2444 for (FunctionArgument arg : function.getArguments()) {
2445 if (TypeUtils.isNumber(arg.getArgumentType())) {
2446 args.add(new DataBinding<>("0", bindingSelector.getBindable(), arg.getArgumentType(),
2447 BindingDefinitionType.GET));
2448 }
2449 else {
2450 args.add(new DataBinding<>("null", bindingSelector.getBindable(), arg.getArgumentType(),
2451 BindingDefinitionType.GET));
2452 }
2453 }
2454 FunctionPathElement newFunctionPathElement = bindingSelector.getBindable().getBindingFactory().makeFunctionPathElement(
2455 currentElement != null ? currentElement.getParent() : bindingValue.getLastBindingPathElement(), function, args);
2456
2457 if (newFunctionPathElement != null) {
2458
2459
2460
2461
2462 bindingValue.setBindingPathElementAtIndex(newFunctionPathElement, index - 1);
2463 binding.setExpression(bindingValue);
2464 bindingSelector.fireEditedObjectChanged();
2465
2466 }
2467 else {
2468 LOGGER.warning("Cannot retrieve new FunctionPathElement for " + bindingValue.getLastBindingPathElement()
2469 + " function=" + function);
2470 }
2471 }
2472
2473 }
2474 }
2475 }
2476 }