1 using System;
2 using System.Linq;
3 using System.Reactive.Disposables;
4 using System.Reactive.Linq;
5 using System.Windows.Forms;
6 using OpenBveApi.Interface;
7 using Reactive.Bindings.Binding;
8 using Reactive.Bindings.Extensions;
9 using TrainEditor2.Extensions;
10 using TrainEditor2.ViewModels.Others;
11 using TrainEditor2.ViewModels.Panels;
12 
13 namespace TrainEditor2.Views
14 {
15 	public partial class FormTouch : Form
16 	{
17 		private readonly CompositeDisposable disposable;
18 
19 		private readonly TouchElementViewModel touch;
20 
21 		private TreeNode TreeViewTouchTopNode
22 		{
23 			get
24 			{
25 				if (treeViewTouch.Nodes.Count == 0)
26 				{
27 					treeViewTouch.Nodes.Add(new TreeNode());
28 				}
29 
30 				return treeViewTouch.Nodes[0];
31 			}
32 			// ReSharper disable once UnusedMember.Local
33 			set
34 			{
35 				treeViewTouch.Nodes.Clear();
36 				treeViewTouch.Nodes.Add(value);
37 				treeViewTouch.ExpandAll();
38 				treeViewTouch.SelectedNode = treeViewTouch.Nodes
39 					.OfType<TreeNode>()
40 					.Select(z => FormEditor.SearchTreeNode(touch.SelectedTreeItem.Value, z))
41 					.FirstOrDefault(z => z != null);
42 				touch.SelectedTreeItem.ForceNotify();
43 			}
44 		}
45 
46 		private ListViewItem ListViewTouchSelectedItem
47 		{
48 			get
49 			{
50 				if (listViewTouch.SelectedItems.Count == 1)
51 				{
52 					return listViewTouch.SelectedItems[0];
53 				}
54 
55 				return null;
56 			}
57 			// ReSharper disable once UnusedMember.Local
58 			set
59 			{
60 				foreach (ListViewItem item in listViewTouch.Items.OfType<ListViewItem>().Where(x => x.Selected))
61 				{
62 					item.Selected = false;
63 				}
64 
65 				if (value != null)
66 				{
67 					value.Selected = true;
68 				}
69 			}
70 		}
71 
FormTouch(TouchElementViewModel touch)72 		internal FormTouch(TouchElementViewModel touch)
73 		{
74 			disposable = new CompositeDisposable();
75 			CompositeDisposable listItemDisposable = new CompositeDisposable().AddTo(disposable);
76 			CompositeDisposable entryDisposable = new CompositeDisposable().AddTo(disposable);
77 
78 			this.touch = touch;
79 
80 			InitializeComponent();
81 
82 			touch.TreeItem
83 				.BindTo(
84 					this,
85 					x => x.TreeViewTouchTopNode,
86 					BindingMode.OneWay,
87 					FormEditor.TreeViewItemViewModelToTreeNode
88 				)
89 				.AddTo(disposable);
90 
91 			touch.SelectedTreeItem
92 				.BindTo(
93 					treeViewTouch,
94 					x => x.SelectedNode,
95 					BindingMode.TwoWay,
96 					x => treeViewTouch.Nodes.OfType<TreeNode>().Select(y => FormEditor.SearchTreeNode(x, y)).FirstOrDefault(y => y != null),
97 					x => (TreeViewItemViewModel)x.Tag,
98 					Observable.FromEvent<TreeViewEventHandler, TreeViewEventArgs>(
99 							h => (s, e) => h(e),
100 							h => treeViewTouch.AfterSelect += h,
101 							h => treeViewTouch.AfterSelect -= h
102 						)
103 						.ToUnit()
104 				)
105 				.AddTo(disposable);
106 
107 			touch.SelectedTreeItem
108 				.BindTo(
109 					listViewTouch,
110 					x => x.Enabled,
111 					BindingMode.OneWay,
112 					x => touch.TreeItem.Value.Children.Contains(x)
113 				)
114 				.AddTo(disposable);
115 
116 			touch.ListColumns
117 				.ObserveAddChanged()
118 				.Subscribe(x =>
119 				{
120 					listViewTouch.Columns.Add(FormEditor.ListViewColumnHeaderViewModelToColumnHeader(x));
121 					listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
122 				})
123 				.AddTo(disposable);
124 
125 			touch.ListColumns
126 				.ObserveRemoveChanged()
127 				.Subscribe(y =>
128 				{
129 					foreach (ColumnHeader column in listViewTouch.Columns.OfType<ColumnHeader>().Where(z => z.Tag == y).ToArray())
130 					{
131 						listViewTouch.Columns.Remove(column);
132 					}
133 
134 					listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
135 				})
136 				.AddTo(disposable);
137 
138 			touch.ListColumns
139 				.ObserveResetChanged()
140 				.Subscribe(_ =>
141 				{
142 					listViewTouch.Columns.Clear();
143 					listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
144 				})
145 				.AddTo(disposable);
146 
147 			touch.ListItems
148 				.ObserveAddChanged()
149 				.Subscribe(x =>
150 				{
151 					listViewTouch.Items.Add(FormEditor.ListViewItemViewModelToListViewItem(x));
152 					listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
153 				})
154 				.AddTo(disposable);
155 
156 			touch.ListItems
157 				.ObserveRemoveChanged()
158 				.Subscribe(x =>
159 				{
160 					foreach (ListViewItem item in listViewTouch.Items.OfType<ListViewItem>().Where(y => y.Tag == x).ToArray())
161 					{
162 						listViewTouch.Items.Remove(item);
163 					}
164 
165 					listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
166 				})
167 				.AddTo(disposable);
168 
169 			touch.ListItems
170 				.ObserveResetChanged()
171 				.Subscribe(_ =>
172 				{
173 					listViewTouch.Items.Clear();
174 					listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
175 				})
176 				.AddTo(disposable);
177 
178 			touch.SelectedListItem
179 				.BindTo(
180 					this,
181 					x => x.ListViewTouchSelectedItem,
182 					BindingMode.TwoWay,
183 					x => listViewTouch.Items.OfType<ListViewItem>().FirstOrDefault(y => y.Tag == x),
184 					x => (ListViewItemViewModel)x?.Tag,
185 					Observable.FromEvent<EventHandler, EventArgs>(
186 							h => (s, e) => h(e),
187 							h => listViewTouch.SelectedIndexChanged += h,
188 							h => listViewTouch.SelectedIndexChanged -= h
189 						)
190 						.ToUnit()
191 				)
192 				.AddTo(disposable);
193 
194 			touch.SelectedListItem
195 				.Where(x => x != null)
196 				.Subscribe(x =>
197 				{
198 					listItemDisposable.Dispose();
199 					listItemDisposable = new CompositeDisposable().AddTo(disposable);
200 
201 					x.Texts
202 						.ObserveReplaceChanged()
203 						.Subscribe(_ =>
204 						{
205 							FormEditor.UpdateListViewItem(ListViewTouchSelectedItem, touch.SelectedListItem.Value);
206 							listViewTouch.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
207 						})
208 						.AddTo(listItemDisposable);
209 				})
210 				.AddTo(disposable);
211 
212 			touch.SelectedSoundEntry
213 				.BindTo(
214 					groupBoxTouchSound,
215 					x => x.Enabled,
216 					x => x != null
217 				)
218 				.AddTo(disposable);
219 
220 			touch.SelectedSoundEntry
221 				.Where(x => x != null)
222 				.Subscribe(x =>
223 				{
224 					entryDisposable.Dispose();
225 					entryDisposable = new CompositeDisposable().AddTo(disposable);
226 
227 					BindToSoundEntry(x).AddTo(entryDisposable);
228 				})
229 				.AddTo(disposable);
230 
231 			touch.SelectedCommandEntry
232 				.BindTo(
233 					groupBoxTouchCommand,
234 					x => x.Enabled,
235 					x => x != null
236 				)
237 				.AddTo(disposable);
238 
239 			touch.SelectedCommandEntry
240 				.Where(x => x != null)
241 				.Subscribe(x =>
242 				{
243 					entryDisposable.Dispose();
244 					entryDisposable = new CompositeDisposable().AddTo(disposable);
245 
246 					BindToCommandEntry(x).AddTo(entryDisposable);
247 				})
248 				.AddTo(disposable);
249 
250 			comboBoxTouchCommandName.Items
251 				.AddRange(
252 					Enum.GetValues(typeof(Translations.Command))
253 						.OfType<Translations.Command>()
254 						.Select(c => Translations.CommandInfos.TryGetInfo(c).Name)
255 						.OfType<object>()
256 						.ToArray()
257 				);
258 
259 			new[] { touch.AddSoundEntry, touch.AddCommandEntry }
260 				.BindToButton(buttonTouchAdd)
261 				.AddTo(disposable);
262 
263 			new[] { touch.CopySoundEntry, touch.CopyCommandEntry }
264 				.BindToButton(buttonTouchCopy)
265 				.AddTo(disposable);
266 
267 			new[] { touch.RemoveSoundEntry, touch.RemoveCommandEntry }
268 				.BindToButton(buttonTouchRemove)
269 				.AddTo(disposable);
270 		}
271 
FormTouch_Load(object sender, EventArgs e)272 		private void FormTouch_Load(object sender, EventArgs e)
273 		{
274 			Icon = FormEditor.GetIcon();
275 		}
276 
ButtonOK_Click(object sender, EventArgs e)277 		private void ButtonOK_Click(object sender, EventArgs e)
278 		{
279 			ListViewTouchSelectedItem = null;
280 			treeViewTouch.SelectedNode = TreeViewTouchTopNode;
281 
282 			Close();
283 		}
284 
BindToSoundEntry(TouchElementViewModel.SoundEntryViewModel entry)285 		private IDisposable BindToSoundEntry(TouchElementViewModel.SoundEntryViewModel entry)
286 		{
287 			CompositeDisposable entryDisposable = new CompositeDisposable();
288 
289 			entry.Index
290 				.BindTo(
291 					numericUpDownTouchSoundIndex,
292 					x => x.Value,
293 					BindingMode.TwoWay,
294 					null,
295 					x => (int)x,
296 					Observable.FromEvent<EventHandler, EventArgs>(
297 							h => (s, e) => h(e),
298 							h => numericUpDownTouchSoundIndex.ValueChanged += h,
299 							h => numericUpDownTouchSoundIndex.ValueChanged -= h
300 						)
301 						.ToUnit()
302 				)
303 				.AddTo(entryDisposable);
304 
305 			return entryDisposable;
306 		}
307 
BindToCommandEntry(TouchElementViewModel.CommandEntryViewModel entry)308 		private IDisposable BindToCommandEntry(TouchElementViewModel.CommandEntryViewModel entry)
309 		{
310 			CompositeDisposable entryDisposable = new CompositeDisposable();
311 
312 			entry.Info
313 				.BindTo(
314 					comboBoxTouchCommandName,
315 					x => x.SelectedIndex,
316 					BindingMode.TwoWay,
317 					x => (int)x.Command,
318 					x => Translations.CommandInfos.TryGetInfo((Translations.Command)x),
319 					Observable.FromEvent<EventHandler, EventArgs>(
320 							h => (s, e) => h(e),
321 							h => comboBoxTouchCommandName.SelectedIndexChanged += h,
322 							h => comboBoxTouchCommandName.SelectedIndexChanged -= h
323 						)
324 						.ToUnit()
325 				)
326 				.AddTo(entryDisposable);
327 
328 			entry.Option
329 				.BindTo(
330 					numericUpDownTouchCommandOption,
331 					x => x.Value,
332 					BindingMode.TwoWay,
333 					null,
334 					x => (int)x,
335 					Observable.FromEvent<EventHandler, EventArgs>(
336 							h => (s, e) => h(e),
337 							h => numericUpDownTouchCommandOption.ValueChanged += h,
338 							h => numericUpDownTouchCommandOption.ValueChanged -= h
339 						)
340 						.ToUnit()
341 				)
342 				.AddTo(entryDisposable);
343 
344 			return entryDisposable;
345 		}
346 	}
347 }
348