9c0ad0b317a6cd1f47a5a04492619c9f3b7df0e2
[Mograsim.git] / plugins / net.mograsim.plugin.core / src / net / mograsim / plugin / nature / MachineContextSwtTools.java
1 package net.mograsim.plugin.nature;
2
3 import java.util.Collections;
4 import java.util.HashSet;
5 import java.util.Map;
6 import java.util.Optional;
7 import java.util.Set;
8 import java.util.function.Consumer;
9 import java.util.function.Function;
10
11 import org.eclipse.core.resources.IProject;
12 import org.eclipse.jface.viewers.ComboViewer;
13 import org.eclipse.jface.viewers.IStructuredContentProvider;
14 import org.eclipse.jface.viewers.LabelProvider;
15 import org.eclipse.jface.viewers.ViewerComparator;
16 import org.eclipse.swt.SWT;
17 import org.eclipse.swt.widgets.Combo;
18 import org.eclipse.swt.widgets.Composite;
19 import org.eclipse.swt.widgets.Display;
20
21 import net.mograsim.machine.MachineDefinition;
22 import net.mograsim.machine.MachineRegistry;
23 import net.mograsim.plugin.nature.ProjectContextEvent.ProjectContextEventType;
24
25 public final class MachineContextSwtTools
26 {
27         private static final Map<String, MachineDefinition> INSTALLED_MACHINES = MachineRegistry.getInstalledMachines();
28         private static final Map<IProject, MachineContext> PROJECT_MACHINE_CONTEXTS = ProjectMachineContext.getAllProjectMachineContexts();
29
30         private MachineContextSwtTools()
31         {
32                 // not instantiable
33         }
34
35         public static MachineCombo createMachineSelector(Composite parent, int style)
36         {
37                 return new MachineCombo(parent, style);
38         }
39
40         public static MograsimProjectCombo createMograsimProjectSelector(Composite parent, int style)
41         {
42                 return new MograsimProjectCombo(parent, style);
43         }
44
45         public abstract static class AdvancedCombo<T>
46         {
47                 final ComboViewer combo;
48                 private Set<Consumer<T>> listeners;
49
50                 public AdvancedCombo(Composite parent, Function<T, String> labelProvider)
51                 {
52                         this(parent, SWT.NONE, labelProvider);
53                 }
54
55                 public AdvancedCombo(Composite parent, int style, Function<T, String> labelProvider)
56                 {
57                         listeners = Collections.synchronizedSet(new HashSet<>());
58                         combo = new ComboViewer(parent, style);
59                         combo.addSelectionChangedListener(e -> updateSelection());
60                         combo.setComparator(new ViewerComparator());
61                         combo.setLabelProvider(new LabelProvider()
62                         {
63                                 @SuppressWarnings("unchecked")
64                                 @Override
65                                 public String getText(Object element)
66                                 {
67                                         try
68                                         {
69                                                 return labelProvider.apply((T) element);
70                                         }
71                                         catch (ClassCastException e)
72                                         {
73                                                 return "Invalid Element: " + e.getLocalizedMessage();
74                                         }
75                                 }
76                         });
77                 }
78
79                 public final ComboViewer getCombo()
80                 {
81                         return combo;
82                 }
83
84                 @SuppressWarnings("unchecked")
85                 public T getSelection()
86                 {
87                         return (T) combo.getStructuredSelection().getFirstElement();
88                 }
89
90                 private void updateSelection()
91                 {
92                         T active = getSelection();
93                         listeners.forEach(l -> l.accept(active));
94                 }
95
96                 public final void addListener(Consumer<T> listener)
97                 {
98                         listeners.add(listener);
99                 }
100
101                 public final void removeListener(Consumer<T> listener)
102                 {
103                         listeners.remove(listener);
104                 }
105
106                 public void refreshContent()
107                 {
108                         Display.getDefault().asyncExec(combo::refresh);
109                 }
110         }
111
112         public static class MachineCombo extends AdvancedCombo<MachineDefinition>
113         {
114                 private static final Set<MachineCombo> machineComboListeners = Collections.synchronizedSet(new HashSet<>());
115
116                 static
117                 {
118                         MachineRegistry.addMachineRegistryListener(newMap -> machineComboListeners.forEach(AdvancedCombo::refreshContent));
119                 }
120
121                 public MachineCombo(Composite parent)
122                 {
123                         this(parent, SWT.NONE);
124                 }
125
126                 public MachineCombo(Composite parent, int style)
127                 {
128                         super(parent, style, MachineDefinition::getId);
129                         combo.setContentProvider(new IStructuredContentProvider()
130                         {
131                                 @Override
132                                 public void dispose()
133                                 {
134                                         machineComboListeners.remove(MachineCombo.this);
135                                 }
136
137                                 @Override
138                                 public Object[] getElements(Object inputElement)
139                                 {
140                                         return INSTALLED_MACHINES.values().toArray();
141                                 }
142                         });
143                         combo.setInput(this);
144                         machineComboListeners.add(this);
145                 }
146         }
147
148         public static class MograsimProjectCombo extends AdvancedCombo<IProject>
149         {
150                 private static final Set<MograsimProjectCombo> projectComboListeners = Collections.synchronizedSet(new HashSet<>());
151
152                 static
153                 {
154                         ProjectMachineContext.addProjectContextListener(projectEvent ->
155                         {
156                                 if (projectEvent.getEventType() != ProjectContextEventType.OTHER_CHANGE)
157                                         projectComboListeners.forEach(AdvancedCombo::refreshContent);
158                         });
159                 }
160
161                 public MograsimProjectCombo(Composite parent)
162                 {
163                         this(parent, SWT.NONE);
164                 }
165
166                 public MograsimProjectCombo(Composite parent, int style)
167                 {
168                         super(parent, style, IProject::getName);
169                         combo.setContentProvider(new IStructuredContentProvider()
170                         {
171                                 @Override
172                                 public void dispose()
173                                 {
174                                         projectComboListeners.remove(MograsimProjectCombo.this);
175                                 }
176
177                                 @Override
178                                 public Object[] getElements(Object inputElement)
179                                 {
180                                         return PROJECT_MACHINE_CONTEXTS.values().stream().filter(mc -> mc.getProject().isOpen() && mc.isCurrentyValid())
181                                                         .map(MachineContext::getProject).toArray();
182                                 }
183                         });
184                         combo.setInput(this);
185                         projectComboListeners.add(this);
186                 }
187         }
188
189         /**
190          * XXX: of no use?
191          */
192         static Optional<String> getSelection(Combo c)
193         {
194                 int selectionIndex = c.getSelectionIndex();
195                 if (selectionIndex == -1)
196                         return Optional.empty();
197                 return Optional.of(c.getItem(selectionIndex));
198         }
199 }