~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/AddIns/BackendBindings/XamlBinding/XamlBinding/PowerToys/Dialogs/EditGridColumnsAndRowsDialog.xaml.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
using System;
 
5
using System.Collections.Generic;
 
6
using System.Diagnostics;
 
7
using System.Globalization;
 
8
using System.Linq;
 
9
using System.Text;
 
10
using System.Windows;
 
11
using System.Windows.Controls;
 
12
using System.Windows.Data;
 
13
using System.Windows.Documents;
 
14
using System.Windows.Input;
 
15
using System.Windows.Media;
 
16
using System.Windows.Shapes;
 
17
using System.Xml.Linq;
 
18
 
 
19
using ICSharpCode.Core;
 
20
using ICSharpCode.SharpDevelop;
 
21
 
 
22
namespace ICSharpCode.XamlBinding.PowerToys.Dialogs
 
23
{
 
24
        /// <summary>
 
25
        /// Interaction logic for EditGridColumnsAndRowsDialog.xaml
 
26
        /// </summary>
 
27
        public partial class EditGridColumnsAndRowsDialog : Window
 
28
        {
 
29
                readonly XName rowDefsName, colDefsName;
 
30
                readonly XName rowDefName, colDefName;
 
31
                
 
32
                readonly XName gridRowName = XName.Get("Grid.Row");
 
33
                readonly XName gridColName = XName.Get("Grid.Column");
 
34
                
 
35
                readonly string currentWpfNamespace;
 
36
                
 
37
                XElement gridTree;
 
38
                XElement rowDefitions;
 
39
                XElement colDefitions;
 
40
                IList<XElement> additionalProperties;
 
41
                
 
42
                bool gridLengthInvalid;
 
43
                
 
44
                Stack<UndoStep> undoStack;
 
45
                Stack<UndoStep> redoStack;
 
46
                
 
47
                public EditGridColumnsAndRowsDialog(XElement gridTree)
 
48
                {
 
49
                        InitializeComponent();
 
50
                        
 
51
                        currentWpfNamespace = gridTree.GetCurrentNamespaces()
 
52
                                .First(i => CompletionDataHelper.WpfXamlNamespaces.Contains(i));
 
53
                        
 
54
                        rowDefsName = XName.Get("Grid.RowDefinitions", currentWpfNamespace);
 
55
                        colDefsName = XName.Get("Grid.ColumnDefinitions", currentWpfNamespace);
 
56
                        
 
57
                        rowDefName = XName.Get("RowDefinition", currentWpfNamespace);
 
58
                        colDefName = XName.Get("ColumnDefinition", currentWpfNamespace);
 
59
                        
 
60
                        this.gridTree = gridTree;
 
61
                        this.rowDefitions = gridTree.Element(rowDefsName) ?? new XElement(rowDefsName);
 
62
                        this.colDefitions = gridTree.Element(colDefsName) ?? new XElement(colDefsName);
 
63
                        
 
64
                        if (this.rowDefitions.Parent != null)
 
65
                                this.rowDefitions.Remove();
 
66
                        if (this.colDefitions.Parent != null)
 
67
                                this.colDefitions.Remove();
 
68
                        
 
69
                        foreach (var height in this.rowDefitions.Elements().Select(row => row.Attribute("Height"))) {
 
70
                                if (height.Value.Trim() == "1*")
 
71
                                        height.Value = "*";
 
72
                                else
 
73
                                        height.Value = height.Value.Trim();
 
74
                        }
 
75
                        
 
76
                        foreach (var width in this.colDefitions.Elements().Select(col => col.Attribute("Width"))) {
 
77
                                if (width.Value.Trim() == "1*")
 
78
                                        width.Value = "*";
 
79
                                else
 
80
                                        width.Value = width.Value.Trim();
 
81
                        }
 
82
                        
 
83
                        this.additionalProperties = gridTree.Elements().Where(e => e.Name.LocalName.Contains(".")).ToList();
 
84
                        this.additionalProperties.ForEach(item => { if (item.Parent != null) item.Remove(); });
 
85
                        
 
86
                        this.redoStack = new Stack<UndoStep>();
 
87
                        this.undoStack = new Stack<UndoStep>();
 
88
                        
 
89
                        CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo, delegate { UndoItemClick(null, null); }));
 
90
                        CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo, delegate { RedoItemClick(null, null); }));
 
91
                        
 
92
                        int maxCols = Math.Max(this.colDefitions.Elements().Count(), 1);
 
93
                        int maxRows = Math.Max(this.rowDefitions.Elements().Count(), 1);
 
94
                        
 
95
                        this.gridTree.Elements().ForEach(el => NormalizeElementGridIndices(el, maxCols, maxRows));
 
96
                        
 
97
                        RebuildGrid();
 
98
                }
 
99
                
 
100
                void NormalizeElementGridIndices(XElement element, int maxCols, int maxRows)
 
101
                {
 
102
                        XAttribute a = element.Attribute(gridColName);
 
103
                        XAttribute b = element.Attribute(gridRowName);
 
104
                        int value;
 
105
                        if (a != null && int.TryParse(a.Value, out value))
 
106
                                element.SetAttributeValue(gridColName, Utils.MinMax(value, 0, maxCols - 1));
 
107
                        else
 
108
                                element.SetAttributeValue(gridColName, 0);
 
109
                        if (b != null && int.TryParse(b.Value, out value))
 
110
                                element.SetAttributeValue(gridRowName, Utils.MinMax(value, 0, maxRows - 1));
 
111
                        else
 
112
                                element.SetAttributeValue(gridRowName, 0);
 
113
                }
 
114
                
 
115
                static MenuItem CreateItem(string header, Action<StackPanel> clickAction, StackPanel senderItem)
 
116
                {
 
117
                        MenuItem item = new MenuItem();
 
118
                        
 
119
                        item.Header = header;
 
120
                        item.Click += delegate { clickAction(senderItem); };
 
121
                        
 
122
                        return item;
 
123
                }
 
124
                
 
125
                static MenuItem CreateItem(string header, Action<int, int> clickAction, int cellIndex)
 
126
                {
 
127
                        MenuItem item = new MenuItem();
 
128
                        
 
129
                        item.Header = header;
 
130
                        item.Click += delegate { clickAction(cellIndex, 1); };
 
131
                        
 
132
                        return item;
 
133
                }
 
134
                
 
135
                void InsertAbove(StackPanel block)
 
136
                {
 
137
                        UpdateUndoRedoState();
 
138
                        
 
139
                        int row = (int)block.GetValue(Grid.RowProperty);
 
140
                        
 
141
                        var newRow = new XElement(rowDefName);
 
142
                        newRow.SetAttributeValue(XName.Get("Height"), "*");
 
143
                        var items = rowDefitions.Elements().Skip(row);
 
144
                        var selItem = items.FirstOrDefault();
 
145
                        if (selItem != null)
 
146
                                selItem.AddBeforeSelf(newRow);
 
147
                        else
 
148
                                rowDefitions.Add(newRow);
 
149
                        
 
150
                        var controls = gridTree
 
151
                                .Elements()
 
152
                                .Where(
 
153
                                        element => {
 
154
                                                var rowAttrib = element.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
155
                                                int rowAttribValue = 0;
 
156
                                                if (int.TryParse(rowAttrib.Value, out rowAttribValue))
 
157
                                                        return rowAttribValue >= row;
 
158
                                                
 
159
                                                return false;
 
160
                                        }
 
161
                                );
 
162
                        
 
163
                        controls.ForEach(item => MoveRowItem(item, 1));
 
164
                        
 
165
                        RebuildGrid();
 
166
                }
 
167
                
 
168
                void InsertBelow(StackPanel block)
 
169
                {
 
170
                        UpdateUndoRedoState();
 
171
                        
 
172
                        int row = (int)block.GetValue(Grid.RowProperty);
 
173
                        
 
174
                        var newRow = new XElement(rowDefName);
 
175
                        newRow.SetAttributeValue(XName.Get("Height"), "*");
 
176
                        var items = rowDefitions.Elements().Skip(row);
 
177
                        var selItem = items.FirstOrDefault();
 
178
                        if (selItem != null)
 
179
                                selItem.AddAfterSelf(newRow);
 
180
                        else
 
181
                                rowDefitions.Add(newRow);
 
182
                        
 
183
                        var controls = gridTree
 
184
                                .Elements()
 
185
                                .Where(
 
186
                                        element => {
 
187
                                                var rowAttrib = element.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
188
                                                int rowAttribValue = 0;
 
189
                                                if (int.TryParse(rowAttrib.Value, out rowAttribValue))
 
190
                                                        return rowAttribValue > row;
 
191
                                                
 
192
                                                return false;
 
193
                                        }
 
194
                                );
 
195
                        
 
196
                        controls.ForEach(item => MoveRowItem(item, 1));
 
197
                        
 
198
                        RebuildGrid();
 
199
                }
 
200
                
 
201
                void MoveUp(int row, int steps)
 
202
                {
 
203
                        if (steps < 1 || row - steps < 0)
 
204
                                return;
 
205
                        
 
206
                        UpdateUndoRedoState();
 
207
                        
 
208
                        var selItem = rowDefitions.Elements().Skip(row).FirstOrDefault();
 
209
                        if (selItem == null)
 
210
                                return;
 
211
                        selItem.Remove();
 
212
                        
 
213
                        var before = rowDefitions.Elements().Skip(row - steps).FirstOrDefault();
 
214
                        if (before == null)
 
215
                                return;
 
216
                        before.AddBeforeSelf(selItem);
 
217
                        
 
218
                        var controls = gridTree.Elements().Where(element => IsSameRow(element, row)).ToList();
 
219
                        
 
220
                        var controlsDown = gridTree.Elements()
 
221
                                .Where(
 
222
                                        element2 => {
 
223
                                                var rowAttrib = element2.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
224
                                                int rowAttribValue = 0;
 
225
                                                if (int.TryParse(rowAttrib.Value, out rowAttribValue))
 
226
                                                        return rowAttribValue < row && rowAttribValue >= (row - steps);
 
227
                                                
 
228
                                                return false;
 
229
                                        }
 
230
                                ).ToList();
 
231
                        
 
232
                        controls.ForEach(item => MoveRowItem(item, -steps));
 
233
                        controlsDown.ForEach(item2 => MoveRowItem(item2, 1));
 
234
                        
 
235
                        RebuildGrid();
 
236
                }
 
237
                
 
238
                bool IsSameRow(XElement element, int row)
 
239
                {
 
240
                        var rowAttrib = element.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
241
                        int rowAttribValue = 0;
 
242
                        if (int.TryParse(rowAttrib.Value, out rowAttribValue))
 
243
                                return rowAttribValue == row;
 
244
                        
 
245
                        return false;
 
246
                }
 
247
                
 
248
                void MoveDown(int row, int steps)
 
249
                {
 
250
                        if (steps < 1 || row + steps > rowDefitions.Elements().Count())
 
251
                                return;
 
252
                        
 
253
                        UpdateUndoRedoState();
 
254
 
 
255
                        var selItem = rowDefitions.Elements().Skip(row).FirstOrDefault();
 
256
                        if (selItem == null)
 
257
                                return;
 
258
                        selItem.Remove();
 
259
                        var before = rowDefitions.Elements().Skip(row + steps).FirstOrDefault();
 
260
                        if (before == null)
 
261
                                rowDefitions.Add(selItem);
 
262
                        else
 
263
                                before.AddBeforeSelf(selItem);
 
264
                        
 
265
                        var controls = gridTree.Elements().Where(element => IsSameRow(element, row)).ToList();
 
266
                        
 
267
                        var controlsUp = gridTree.Elements()
 
268
                                .Where(
 
269
                                        element2 => {
 
270
                                                var rowAttrib = element2.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
271
                                                int rowAttribValue = 0;
 
272
                                                if (int.TryParse(rowAttrib.Value, out rowAttribValue))
 
273
                                                        return rowAttribValue > row && rowAttribValue <= (row + steps);
 
274
                                                
 
275
                                                return false;
 
276
                                        }
 
277
                                ).ToList();
 
278
                        
 
279
                        controls.ForEach(item => MoveRowItem(item, steps));
 
280
                        controlsUp.ForEach(item2 => MoveRowItem(item2, -1));
 
281
                        
 
282
                        RebuildGrid();
 
283
                }
 
284
                
 
285
                void DeleteRow(StackPanel block)
 
286
                {
 
287
                        int row = (int)block.GetValue(Grid.RowProperty);
 
288
                        UpdateUndoRedoState();
 
289
 
 
290
                        var items = rowDefitions.Elements().Skip(row);
 
291
                        var selItem = items.FirstOrDefault();
 
292
                        if (selItem != null)
 
293
                                selItem.Remove();
 
294
                        
 
295
                        var controls = gridTree.Elements()
 
296
                                .Where(
 
297
                                        element => {
 
298
                                                var rowAttrib = element.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
299
                                                int rowAttribValue = 0;
 
300
                                                if (int.TryParse(rowAttrib.Value, out rowAttribValue))
 
301
                                                        return rowAttribValue >= row;
 
302
                                                
 
303
                                                return false;
 
304
                                        }
 
305
                                );
 
306
                        
 
307
                        controls.ForEach(item => MoveRowItem(item, -1));
 
308
                        
 
309
                        RebuildGrid();
 
310
                }
 
311
                
 
312
                void InsertBefore(StackPanel block)
 
313
                {
 
314
                        int column = (int)block.GetValue(Grid.ColumnProperty);
 
315
                        UpdateUndoRedoState();
 
316
 
 
317
                        var newColumn = new XElement(colDefName);
 
318
                        newColumn.SetAttributeValue(XName.Get("Width"), "*");
 
319
                        var items = colDefitions.Elements().Skip(column);
 
320
                        var selItem = items.FirstOrDefault();
 
321
                        if (selItem != null)
 
322
                                selItem.AddBeforeSelf(newColumn);
 
323
                        else
 
324
                                colDefitions.Add(newColumn);
 
325
                        
 
326
                        var controls = gridTree.Elements()
 
327
                                .Where(
 
328
                                        element => {
 
329
                                                var colAttrib = element.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
330
                                                int colAttribValue = 0;
 
331
                                                if (int.TryParse(colAttrib.Value, out colAttribValue))
 
332
                                                        return colAttribValue >= column;
 
333
                                                
 
334
                                                return false;
 
335
                                        }
 
336
                                );
 
337
                        
 
338
                        controls.ForEach(item => MoveColumnItem(item, 1));
 
339
                        
 
340
                        RebuildGrid();
 
341
                }
 
342
                
 
343
                void InsertAfter(StackPanel block)
 
344
                {
 
345
                        int column = (int)block.GetValue(Grid.ColumnProperty);
 
346
                        UpdateUndoRedoState();
 
347
 
 
348
                        var newColumn = new XElement(colDefName);
 
349
                        newColumn.SetAttributeValue(XName.Get("Width"), "*");
 
350
                        var items = colDefitions.Elements().Skip(column);
 
351
                        var selItem = items.FirstOrDefault();
 
352
                        if (selItem != null)
 
353
                                selItem.AddAfterSelf(newColumn);
 
354
                        else
 
355
                                colDefitions.Add(newColumn);
 
356
                        
 
357
                        var controls = gridTree
 
358
                                .Elements()
 
359
                                .Where(
 
360
                                        element => {
 
361
                                                var colAttrib = element.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
362
                                                int colAttribValue = 0;
 
363
                                                if (int.TryParse(colAttrib.Value, out colAttribValue))
 
364
                                                        return colAttribValue > column;
 
365
                                                
 
366
                                                return false;
 
367
                                        }
 
368
                                );
 
369
                        
 
370
                        controls.ForEach(item => MoveColumnItem(item, 1));
 
371
                        
 
372
                        RebuildGrid();
 
373
                }
 
374
                
 
375
                void MoveLeft(int column, int steps)
 
376
                {
 
377
                        if (steps < 1 || column - steps < 0)
 
378
                                return;
 
379
                        
 
380
                        UpdateUndoRedoState();
 
381
                        
 
382
                        var selItem = colDefitions.Elements().Skip(column).FirstOrDefault();
 
383
                        if (selItem == null)
 
384
                                return;
 
385
                        selItem.Remove();
 
386
                        var before = colDefitions.Elements().Skip(column - steps).FirstOrDefault();
 
387
                        if (before == null)
 
388
                                return;
 
389
                        before.AddBeforeSelf(selItem);
 
390
                        
 
391
                        var controls = gridTree.Elements().Where(element => IsSameColumn(element, column)).ToList();
 
392
                        
 
393
                        var controlsLeft = gridTree
 
394
                                .Elements()
 
395
                                .Where(
 
396
                                        element2 => {
 
397
                                                var colAttrib = element2.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
398
                                                int colAttribValue = 0;
 
399
                                                if (int.TryParse(colAttrib.Value, out colAttribValue))
 
400
                                                        return colAttribValue < column && colAttribValue >= (column - steps);
 
401
                                                
 
402
                                                return false;
 
403
                                        }
 
404
                                ).ToList();
 
405
                        
 
406
                        controls.ForEach(item => MoveColumnItem(item, -steps));
 
407
                        controlsLeft.ForEach(item => MoveColumnItem(item, 1));
 
408
 
 
409
                        
 
410
                        RebuildGrid();
 
411
                }
 
412
                
 
413
                bool IsSameColumn(XElement element, int column)
 
414
                {
 
415
                        var colAttrib = element.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
416
                        int colAttribValue = 0;
 
417
                        if (int.TryParse(colAttrib.Value, out colAttribValue))
 
418
                                return colAttribValue == column;
 
419
                        
 
420
                        return false;
 
421
                }
 
422
                
 
423
                void MoveColumnItem(XElement item, int steps)
 
424
                {
 
425
                        var colAttrib = item.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
426
                        item.SetAttributeValue(gridColName, int.Parse(colAttrib.Value, CultureInfo.InvariantCulture) + steps);
 
427
                }
 
428
                
 
429
                void MoveRowItem(XElement item, int steps)
 
430
                {
 
431
                        var rowAttrib = item.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
432
                        item.SetAttributeValue(gridRowName, int.Parse(rowAttrib.Value, CultureInfo.InvariantCulture) + steps);
 
433
                }
 
434
                
 
435
                void MoveRight(int column, int steps)
 
436
                {
 
437
                        if (steps < 1 || column + steps > colDefitions.Elements().Count())
 
438
                                return;
 
439
                        
 
440
                        UpdateUndoRedoState();
 
441
                        
 
442
                        var selItem = colDefitions.Elements().Skip(column).FirstOrDefault();
 
443
                        if (selItem == null)
 
444
                                return;
 
445
                        selItem.Remove();
 
446
                        var before = colDefitions.Elements().Skip(column + steps).FirstOrDefault();
 
447
                        if (before == null)
 
448
                                colDefitions.Add(selItem);
 
449
                        else
 
450
                                before.AddBeforeSelf(selItem);
 
451
                        
 
452
                        var controls = gridTree.Elements().Where(element => IsSameColumn(element, column)).ToList();
 
453
                        
 
454
                        var controlsRight = gridTree
 
455
                                .Elements()
 
456
                                .Where(
 
457
                                        element2 => {
 
458
                                                var colAttrib = element2.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
459
                                                int colAttribValue = 0;
 
460
                                                if (int.TryParse(colAttrib.Value, out colAttribValue))
 
461
                                                        return colAttribValue > column && colAttribValue <= (column + steps);
 
462
                                                
 
463
                                                return false;
 
464
                                        }
 
465
                                ).ToList();
 
466
                        
 
467
                        controls.ForEach(item => MoveColumnItem(item, steps));
 
468
                        controlsRight.ForEach(item2 => MoveColumnItem(item2, -1));
 
469
                        
 
470
                        RebuildGrid();
 
471
                }
 
472
                
 
473
                void DeleteColumn(StackPanel block)
 
474
                {
 
475
                        int column = (int)block.GetValue(Grid.ColumnProperty);
 
476
                        UpdateUndoRedoState();
 
477
 
 
478
                        var items = colDefitions.Elements().Skip(column);
 
479
                        var selItem = items.FirstOrDefault();
 
480
                        if (selItem != null)
 
481
                                selItem.Remove();
 
482
                        
 
483
                        var controls = gridTree
 
484
                                .Elements()
 
485
                                .Where(
 
486
                                        element => {
 
487
                                                var colAttrib = element.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
488
                                                int colAttribValue = 0;
 
489
                                                if (int.TryParse(colAttrib.Value, out colAttribValue))
 
490
                                                        return colAttribValue >= column;
 
491
                                                
 
492
                                                return false;
 
493
                                        }
 
494
                                );
 
495
                        
 
496
                        controls.ForEach(item => MoveColumnItem(item, -1));
 
497
 
 
498
                        
 
499
                        RebuildGrid();
 
500
                }
 
501
                
 
502
                void BtnCancelClick(object sender, RoutedEventArgs e)
 
503
                {
 
504
                        this.DialogResult = false;
 
505
                }
 
506
                
 
507
                void BtnOKClick(object sender, RoutedEventArgs e)
 
508
                {
 
509
                        if (gridLengthInvalid) {
 
510
                                MessageService.ShowError("Grid is invalid, please check the row heights and column widths!");
 
511
                                return;
 
512
                        }
 
513
                        
 
514
                        this.DialogResult = true;
 
515
                }
 
516
                
 
517
                void RebuildGrid()
 
518
                {
 
519
                        if (this.marker != null) {
 
520
                                AdornerLayer.GetAdornerLayer(this.buttonPanel).Remove(this.marker);
 
521
                                AdornerLayer.GetAdornerLayer(this.dropPanel).Remove(this.marker);
 
522
                                this.marker = null;
 
523
                        }
 
524
                        
 
525
                        this.gridDisplay.Children.Clear();
 
526
                        this.gridDisplay.RowDefinitions.Clear();
 
527
                        this.gridDisplay.ColumnDefinitions.Clear();
 
528
                        
 
529
                        
 
530
                        this.columnWidthGrid.ColumnDefinitions.Clear();
 
531
                        this.columnWidthGrid.Children.Clear();
 
532
                        
 
533
                        this.rowHeightGrid.RowDefinitions.Clear();
 
534
                        this.rowHeightGrid.Children.Clear();
 
535
                        
 
536
                        int rows = rowDefitions.Elements().Count();
 
537
                        int cols = colDefitions.Elements().Count();
 
538
                        
 
539
                        if (rows == 0) {
 
540
                                rowDefitions.Add(new XElement(rowDefName).AddAttribute("Height", "*"));
 
541
                                rows = 1;
 
542
                        }
 
543
                        if (cols == 0) {
 
544
                                colDefitions.Add(new XElement(colDefName).AddAttribute("Width", "*"));
 
545
                                cols = 1;
 
546
                        }
 
547
                        
 
548
                        for (int i = 0; i < cols; i++) {
 
549
                                this.gridDisplay.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
 
550
                                this.columnWidthGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
 
551
                                GridLengthEditor editor = new GridLengthEditor(Orientation.Horizontal, i, (colDefitions.Elements().ElementAt(i).Attribute("Width") ?? new XAttribute("Width", "")).Value);
 
552
                                
 
553
                                editor.SelectedValueChanged += new EventHandler<GridLengthSelectionChangedEventArgs>(EditorSelectedValueChanged);
 
554
                                editor.Deleted += new EventHandler<GridLengthSelectionChangedEventArgs>(EditorDeleted);
 
555
                                editor.MouseLeftButtonDown += new MouseButtonEventHandler(EditorMouseLeftButtonDown);
 
556
                                editor.Drop += new DragEventHandler(EditorDrop);
 
557
                                editor.DragOver += new DragEventHandler(EditorDragOver);
 
558
                                
 
559
                                editor.AllowDrop = true;
 
560
                                
 
561
                                this.columnWidthGrid.Children.Add(editor);
 
562
                                
 
563
                                Button leftAddButton = new Button() {
 
564
                                        Content = "+",
 
565
                                        HorizontalAlignment = HorizontalAlignment.Left,
 
566
                                        Margin = new Thickness(-10, 10, 5,10),
 
567
                                        Padding = new Thickness(3),
 
568
                                        Tag = i
 
569
                                };
 
570
                                
 
571
                                leftAddButton.Click += BtnAddColumnClick;
 
572
                                
 
573
                                leftAddButton.SetValue(Grid.ColumnProperty, i);
 
574
                                this.columnWidthGrid.Children.Add(leftAddButton);
 
575
                                
 
576
                                if (cols == i + 1) {
 
577
                                        Button rightAddButton = new Button() {
 
578
                                                Content = "+",
 
579
                                                HorizontalAlignment = HorizontalAlignment.Right,
 
580
                                                Margin = new Thickness(5, 10, 0, 10),
 
581
                                                Padding = new Thickness(3)
 
582
                                        };
 
583
                                        
 
584
                                        rightAddButton.Click += BtnAddColumnClick;
 
585
                                        
 
586
                                        rightAddButton.SetValue(Grid.ColumnProperty, i);
 
587
                                        this.columnWidthGrid.Children.Add(rightAddButton);
 
588
                                }
 
589
                        }
 
590
                        
 
591
                        for (int i = 0; i < rows; i++) {
 
592
                                this.gridDisplay.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
 
593
                                
 
594
                                this.rowHeightGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
 
595
                                GridLengthEditor editor = new GridLengthEditor(Orientation.Vertical, i, (rowDefitions.Elements().ElementAt(i).Attribute("Height") ?? new XAttribute("Height", "")).Value);
 
596
                                
 
597
                                editor.SelectedValueChanged += new EventHandler<GridLengthSelectionChangedEventArgs>(EditorSelectedValueChanged);
 
598
                                editor.Deleted += new EventHandler<GridLengthSelectionChangedEventArgs>(EditorDeleted);
 
599
                                editor.MouseLeftButtonDown += new MouseButtonEventHandler(EditorMouseLeftButtonDown);
 
600
                                editor.Drop += new DragEventHandler(EditorDrop);
 
601
                                editor.DragOver += new DragEventHandler(EditorDragOver);
 
602
                                
 
603
                                editor.AllowDrop = true;
 
604
                                
 
605
                                this.rowHeightGrid.Children.Add(editor);
 
606
                                
 
607
                                Button topAddButton = new Button() {
 
608
                                        Content = "+",
 
609
                                        VerticalAlignment = VerticalAlignment.Top,
 
610
                                        Margin = new Thickness(10, -10, 10, 5),
 
611
                                        Padding = new Thickness(3),
 
612
                                        Tag = i
 
613
                                };
 
614
                                
 
615
                                topAddButton.Click += BtnAddRowClick;
 
616
                                
 
617
                                topAddButton.SetValue(Grid.RowProperty, i);
 
618
                                this.rowHeightGrid.Children.Add(topAddButton);
 
619
                                
 
620
                                if (rows == i + 1) {
 
621
                                        Button bottomAddButton = new Button() {
 
622
                                                Content = "+",
 
623
                                                VerticalAlignment = VerticalAlignment.Bottom,
 
624
                                                Margin = new Thickness(10, 5, 10, 0),
 
625
                                                Padding = new Thickness(3)
 
626
                                        };
 
627
                                        
 
628
                                        bottomAddButton.Click += BtnAddRowClick;
 
629
                                        
 
630
                                        bottomAddButton.SetValue(Grid.RowProperty, i);
 
631
                                        this.rowHeightGrid.Children.Add(bottomAddButton);
 
632
                                }
 
633
                                
 
634
                                for (int j = 0; j < cols; j++) {
 
635
                                        StackPanel displayRect = new StackPanel() {
 
636
                                                Margin = new Thickness(5),
 
637
                                                Background = Brushes.LightGray,
 
638
                                                Orientation = Orientation.Vertical
 
639
                                        };
 
640
                                        
 
641
                                        displayRect.AllowDrop = true;
 
642
                                        
 
643
                                        displayRect.Drop += new DragEventHandler(DisplayRectDrop);
 
644
                                        displayRect.DragOver += new DragEventHandler(DisplayRectDragOver);
 
645
                                        
 
646
                                        displayRect.Children.AddRange(BuildItemsForCell(i, j));
 
647
                                        
 
648
                                        displayRect.SetValue(Grid.RowProperty, i);
 
649
                                        displayRect.SetValue(Grid.ColumnProperty, j);
 
650
                                        
 
651
                                        displayRect.ContextMenuOpening += new ContextMenuEventHandler(DisplayRectContextMenuOpening);
 
652
                                        
 
653
                                        this.gridDisplay.Children.Add(displayRect);
 
654
                                }
 
655
                        }
 
656
                        
 
657
                        this.InvalidateVisual();
 
658
                }
 
659
 
 
660
                void EditorDragOver(object sender, DragEventArgs e)
 
661
                {
 
662
                        try {
 
663
                                GridLengthEditor target = sender as GridLengthEditor;
 
664
                                GridLengthEditor source = e.Data.GetData(typeof(GridLengthEditor)) as GridLengthEditor;
 
665
                                e.Handled =  true;
 
666
                                
 
667
                                if (marker != null) {
 
668
                                        AdornerLayer.GetAdornerLayer(marker.AdornedElement).Remove(marker);
 
669
                                        marker = null;
 
670
                                }
 
671
                                
 
672
                                if (target != null && source != null && source.Orientation == target.Orientation
 
673
                                    && (target != source && (target.Cell < source.Cell || target.Cell > source.Cell + 1))) {
 
674
                                        marker = DragDropMarkerAdorner.CreateAdornerCellMove(target);
 
675
                                        e.Effects = DragDropEffects.Move;
 
676
                                        return;
 
677
                                }
 
678
                                
 
679
                                e.Effects = DragDropEffects.None;
 
680
                        } catch (Exception ex) {
 
681
                                Core.LoggingService.Error(ex);
 
682
                        }
 
683
                }
 
684
 
 
685
                void EditorDrop(object sender, DragEventArgs e)
 
686
                {
 
687
                        try {
 
688
                                GridLengthEditor source = e.Data.GetData(typeof(GridLengthEditor)) as GridLengthEditor;
 
689
                                GridLengthEditor target = sender as GridLengthEditor;
 
690
                                
 
691
                                if (source != null && target != null) {
 
692
                                        if (source.Orientation == Orientation.Horizontal) {
 
693
                                                if (source.Cell > target.Cell)
 
694
                                                        MoveLeft(source.Cell, Math.Abs(source.Cell - target.Cell));
 
695
                                                else
 
696
                                                        MoveRight(source.Cell, Math.Abs(source.Cell - target.Cell) - 1);
 
697
                                        }
 
698
                                        
 
699
                                        if (source.Orientation == Orientation.Vertical) {
 
700
                                                if (source.Cell > target.Cell)
 
701
                                                        MoveUp(source.Cell, Math.Abs(source.Cell - target.Cell));
 
702
                                                else
 
703
                                                        MoveDown(source.Cell, Math.Abs(source.Cell - target.Cell) - 1);
 
704
                                        }
 
705
                                }
 
706
                        } catch (Exception ex) {
 
707
                                Core.LoggingService.Error(ex);
 
708
                        }
 
709
                }
 
710
 
 
711
                void EditorMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 
712
                {
 
713
                        DragDropEffects allowedEffects = DragDropEffects.Move;
 
714
                        GridLengthEditor editor = sender as GridLengthEditor;
 
715
                        DragDrop.DoDragDrop(editor, editor, allowedEffects);
 
716
                }
 
717
 
 
718
                void EditorDeleted(object sender, GridLengthSelectionChangedEventArgs e)
 
719
                {
 
720
                        if (e.Type == Orientation.Horizontal)
 
721
                                DeleteColumn(gridDisplay.Children.OfType<StackPanel>().First(item => (int)item.GetValue(Grid.ColumnProperty) == e.Cell));
 
722
                        else
 
723
                                DeleteRow(gridDisplay.Children.OfType<StackPanel>().First(item => (int)item.GetValue(Grid.RowProperty) == e.Cell));
 
724
                }
 
725
 
 
726
                void EditorSelectedValueChanged(object sender, GridLengthSelectionChangedEventArgs e)
 
727
                {
 
728
                        UpdateUndoRedoState();
 
729
                        
 
730
                        string value = "Invalid";
 
731
                        
 
732
                        if (e.Value != null)
 
733
                                value = e.Value;
 
734
 
 
735
                        if (e.Type == Orientation.Horizontal)
 
736
                                colDefitions.Elements().ElementAt(e.Cell).SetAttributeValue("Width", value);
 
737
                        else
 
738
                                rowDefitions.Elements().ElementAt(e.Cell).SetAttributeValue("Height", value);
 
739
                        
 
740
                        gridLengthInvalid = colDefitions.Elements().Any(col => (col.Attribute("Width") ?? new XAttribute("Width", "*")).Value == "Invalid")
 
741
                                || rowDefitions.Elements().Any(row => (row.Attribute("Height") ?? new XAttribute("Height", "*")).Value == "Invalid");
 
742
                }
 
743
                
 
744
                DragDropMarkerAdorner marker = null;
 
745
 
 
746
                void DisplayRectDragOver(object sender, DragEventArgs e)
 
747
                {
 
748
                        try {
 
749
                                StackPanel target = sender as StackPanel;
 
750
                                e.Handled =  true;
 
751
                                
 
752
                                if (marker != null) {
 
753
                                        AdornerLayer.GetAdornerLayer(marker.AdornedElement).Remove(marker);
 
754
                                        marker = null;
 
755
                                }
 
756
                                
 
757
                                if (target != null) {
 
758
                                        FrameworkElement element = target.InputHitTest(e.GetPosition(target)) as FrameworkElement;
 
759
                                        if (e.Data.GetData(typeof(XElement)) != null && (element is StackPanel || element.TemplatedParent is Label)) {
 
760
                                                marker = DragDropMarkerAdorner.CreateAdornerContentMove(target, element);
 
761
                                                e.Effects = DragDropEffects.Move;
 
762
                                                return;
 
763
                                        }
 
764
                                }
 
765
                                
 
766
                                e.Effects = DragDropEffects.None;
 
767
                        } catch (Exception ex) {
 
768
                                Core.LoggingService.Error(ex);
 
769
                        }
 
770
                }
 
771
 
 
772
                void DisplayRectDrop(object sender, DragEventArgs e)
 
773
                {
 
774
                        try {
 
775
                                if (e.Data.GetData(typeof(XElement)) != null) {
 
776
                                        XElement data = e.Data.GetData(typeof(XElement)) as XElement;
 
777
                                        
 
778
                                        UpdateUndoRedoState();
 
779
                                        
 
780
                                        StackPanel target = sender as StackPanel;
 
781
                                        int x = (int)target.GetValue(Grid.ColumnProperty);
 
782
                                        int y = (int)target.GetValue(Grid.RowProperty);
 
783
                                        
 
784
                                        data.SetAttributeValue(gridColName, x);
 
785
                                        data.SetAttributeValue(gridRowName, y);
 
786
                                        
 
787
                                        Point p = e.GetPosition(target);
 
788
                                        TextBlock block = target.InputHitTest(p) as TextBlock;
 
789
                                        
 
790
                                        if (block != null) {
 
791
                                                XElement element = block.Tag as XElement;
 
792
                                                data.MoveBefore(element);
 
793
                                        } else {
 
794
                                                XElement parent = gridTree;
 
795
                                                XElement element = parent.Elements().LastOrDefault();
 
796
                                                if (data.Parent != null)
 
797
                                                        data.Remove();
 
798
                                                if (element == null)
 
799
                                                        parent.Add(data);
 
800
                                                else {
 
801
                                                        if (element.Parent == null)
 
802
                                                                parent.Add(data);
 
803
                                                        else
 
804
                                                                element.AddAfterSelf(data);
 
805
                                                }
 
806
                                        }
 
807
                                        
 
808
                                        RebuildGrid();
 
809
                                }
 
810
                        } catch (Exception ex) {
 
811
                                Core.LoggingService.Error(ex);
 
812
                        }
 
813
                }
 
814
                
 
815
                IEnumerable<UIElement> BuildItemsForCell(int row, int column)
 
816
                {
 
817
                        var controls = gridTree
 
818
                                .Elements()
 
819
                                .Where(
 
820
                                        element => {
 
821
                                                var rowAttrib = element.Attribute(gridRowName) ?? new XAttribute(gridRowName, 0);
 
822
                                                var colAttrib = element.Attribute(gridColName) ?? new XAttribute(gridColName, 0);
 
823
                                                return  row.ToString() == rowAttrib.Value && column.ToString() == colAttrib.Value;
 
824
                                        }
 
825
                                );
 
826
                        
 
827
                        foreach (var control in controls) {
 
828
                                var nameAttrib = control.Attribute(XName.Get("Name", CompletionDataHelper.XamlNamespace)) ?? control.Attribute(XName.Get("Name"));
 
829
                                StringBuilder builder = new StringBuilder(control.Name.LocalName);
 
830
                                if (nameAttrib != null)
 
831
                                        builder.Append(" (" + nameAttrib.Value + ")");
 
832
                                
 
833
                                Label label = new Label() {
 
834
                                        Content = builder.ToString(),
 
835
                                        Template = this.Resources["itemTemplate"] as ControlTemplate,
 
836
                                        AllowDrop = true,
 
837
                                        Tag = control
 
838
                                };
 
839
                                
 
840
                                label.MouseLeftButtonDown += new MouseButtonEventHandler(LabelMouseLeftButtonDown);
 
841
 
 
842
                                Debug.Assert(label.Tag != null);
 
843
                                
 
844
                                yield return label;
 
845
                        }
 
846
                }
 
847
 
 
848
                void LabelMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
 
849
                {
 
850
                        DragDropEffects allowedEffects = DragDropEffects.Move;
 
851
                        Label label = sender as Label;
 
852
                        DragDrop.DoDragDrop(label, label.Tag, allowedEffects);
 
853
                }
 
854
                
 
855
                void UpdateUndoRedoState()
 
856
                {
 
857
                        this.undoStack.Push(UndoStep.CreateStep(gridTree, rowDefitions, colDefitions, additionalProperties));
 
858
                        this.redoStack.Clear();
 
859
                }
 
860
                
 
861
                public XElement ConstructedTree
 
862
                {
 
863
                        get {
 
864
                                gridTree.AddFirst(additionalProperties);
 
865
                                gridTree.AddFirst(colDefitions);
 
866
                                gridTree.AddFirst(rowDefitions);
 
867
                                
 
868
                                return gridTree;
 
869
                        }
 
870
                }
 
871
 
 
872
                void DisplayRectContextMenuOpening(object sender, ContextMenuEventArgs e)
 
873
                {
 
874
                        MenuItem undoItem = new MenuItem();
 
875
                        undoItem.Header = "Undo";
 
876
                        undoItem.IsEnabled = undoStack.Count > 0;
 
877
                        undoItem.Click += new RoutedEventHandler(UndoItemClick);
 
878
                        
 
879
                        MenuItem redoItem = new MenuItem();
 
880
                        redoItem.Header = "Redo";
 
881
                        redoItem.IsEnabled = redoStack.Count > 0;
 
882
                        redoItem.Click += new RoutedEventHandler(RedoItemClick);
 
883
                        
 
884
                        StackPanel block = sender as StackPanel;
 
885
                        
 
886
                        ContextMenu menu = new ContextMenu() {
 
887
                                Items = {
 
888
                                        undoItem,
 
889
                                        redoItem,
 
890
                                        new Separator(),
 
891
                                        new MenuItem() {
 
892
                                                Header = "Row",
 
893
                                                Items = {
 
894
                                                        CreateItem("Insert above", InsertAbove, block),
 
895
                                                        CreateItem("Insert below", InsertBelow, block),
 
896
                                                        new Separator(),
 
897
                                                        CreateItem("Move up", MoveUp, (int)block.GetValue(Grid.RowProperty)),
 
898
                                                        CreateItem("Move down", MoveDown, (int)block.GetValue(Grid.RowProperty)),
 
899
                                                        new Separator(),
 
900
                                                        CreateItem("Delete", DeleteRow, block)
 
901
                                                }
 
902
                                        },
 
903
                                        new MenuItem() {
 
904
                                                Header = "Column",
 
905
                                                Items = {
 
906
                                                        CreateItem("Insert before", InsertBefore, block),
 
907
                                                        CreateItem("Insert after", InsertAfter, block),
 
908
                                                        new Separator(),
 
909
                                                        CreateItem("Move left", MoveLeft,  (int)block.GetValue(Grid.ColumnProperty)),
 
910
                                                        CreateItem("Move right", MoveRight, (int)block.GetValue(Grid.ColumnProperty)),
 
911
                                                        new Separator(),
 
912
                                                        CreateItem("Delete", DeleteColumn, block)
 
913
                                                }
 
914
                                        }
 
915
                                }
 
916
                        };
 
917
                        
 
918
                        menu.IsOpen = true;
 
919
                }
 
920
 
 
921
                void RedoItemClick(object sender, RoutedEventArgs e)
 
922
                {
 
923
                        if (redoStack.Count > 0)
 
924
                                HandleSteps(redoStack, undoStack);
 
925
                }
 
926
 
 
927
                void UndoItemClick(object sender, RoutedEventArgs e)
 
928
                {
 
929
                        if (undoStack.Count > 0)
 
930
                                HandleSteps(undoStack, redoStack);
 
931
                }
 
932
                
 
933
                void HandleSteps(Stack<UndoStep> stack1, Stack<UndoStep> stack2)
 
934
                {
 
935
                        UndoStep step = stack1.Pop();
 
936
                        
 
937
                        stack2.Push(UndoStep.CreateStep(gridTree, rowDefitions, colDefitions, additionalProperties));
 
938
                        
 
939
                        this.additionalProperties = step.AdditionalProperties;
 
940
                        this.rowDefitions = step.RowDefinitions;
 
941
                        this.colDefitions = step.ColumnDefinitions;
 
942
                        this.gridTree = step.Tree;
 
943
                        
 
944
                        RebuildGrid();
 
945
                }
 
946
                
 
947
                void BtnDeleteItemClick(object sender, RoutedEventArgs e)
 
948
                {
 
949
                        Button source = e.OriginalSource as Button;
 
950
                        XElement item = source.Tag as XElement;
 
951
                        if (item != null) {
 
952
                                UpdateUndoRedoState();
 
953
                                item.Remove();
 
954
                        }
 
955
                        
 
956
                        RebuildGrid();
 
957
                }
 
958
                
 
959
                void BtnAddRowClick(object sender, RoutedEventArgs e)
 
960
                {
 
961
                        Button b = sender as Button;
 
962
                        if (b.Tag == null) {
 
963
                                InsertBelow(gridDisplay.Children.OfType<StackPanel>()
 
964
                                            .First(item => (int)item.GetValue(Grid.RowProperty) == rowDefitions.Elements().Count() - 1));
 
965
                        } else {
 
966
                                InsertAbove(gridDisplay.Children.OfType<StackPanel>()
 
967
                                            .First(item => (int)item.GetValue(Grid.RowProperty) == (int)b.Tag));
 
968
                        }
 
969
                }
 
970
                
 
971
                void BtnAddColumnClick(object sender, RoutedEventArgs e)
 
972
                {
 
973
                        Button b = sender as Button;
 
974
                        if (b.Tag == null) {
 
975
                                InsertAfter(gridDisplay.Children.OfType<StackPanel>()
 
976
                                            .First(item => (int)item.GetValue(Grid.ColumnProperty) == colDefitions.Elements().Count() - 1));
 
977
                        } else {
 
978
                                InsertBefore(gridDisplay.Children.OfType<StackPanel>()
 
979
                                             .First(item => (int)item.GetValue(Grid.ColumnProperty) == (int)b.Tag));
 
980
                        }
 
981
                }
 
982
                
 
983
                void ButtonPanelDrop(object sender, DragEventArgs e)
 
984
                {
 
985
                        try {
 
986
                                GridLengthEditor source = e.Data.GetData(typeof(GridLengthEditor)) as GridLengthEditor;
 
987
                                
 
988
                                if (source != null)
 
989
                                        MoveDown(source.Cell, Math.Abs(source.Cell - rowDefitions.Elements().Count()) - 1);
 
990
                        } catch (Exception ex) {
 
991
                                Core.LoggingService.Error(ex);
 
992
                        }
 
993
                }
 
994
                
 
995
                void DropPanelDrop(object sender, DragEventArgs e)
 
996
                {
 
997
                        try {
 
998
                                GridLengthEditor source = e.Data.GetData(typeof(GridLengthEditor)) as GridLengthEditor;
 
999
                                
 
1000
                                if (source != null)
 
1001
                                        MoveRight(source.Cell, Math.Abs(source.Cell - colDefitions.Elements().Count()) - 1);
 
1002
                        } catch (Exception ex) {
 
1003
                                Core.LoggingService.Error(ex);
 
1004
                        }
 
1005
                }
 
1006
                
 
1007
                void DropPanelDragOver(object sender, DragEventArgs e)
 
1008
                {
 
1009
                        try {
 
1010
                                StackPanel target = sender as StackPanel;
 
1011
                                GridLengthEditor source = e.Data.GetData(typeof(GridLengthEditor)) as GridLengthEditor;
 
1012
                                e.Handled = true;
 
1013
                                
 
1014
                                if (marker != null) {
 
1015
                                        AdornerLayer.GetAdornerLayer(marker.AdornedElement).Remove(marker);
 
1016
                                        marker = null;
 
1017
                                }
 
1018
                                
 
1019
                                if (target != null && source != null && source.Orientation == Orientation.Horizontal && source.Cell + 1 < colDefitions.Elements().Count()) {
 
1020
                                        marker = DragDropMarkerAdorner.CreateAdornerCellMove(target);
 
1021
                                        e.Effects = DragDropEffects.Move;
 
1022
                                        return;
 
1023
                                }
 
1024
                                
 
1025
                                e.Effects = DragDropEffects.None;
 
1026
                        } catch (Exception ex) {
 
1027
                                Core.LoggingService.Error(ex);
 
1028
                        }
 
1029
                }
 
1030
                
 
1031
                void ButtonPanelDragOver(object sender, DragEventArgs e)
 
1032
                {
 
1033
                        try {
 
1034
                                StackPanel target = sender as StackPanel;
 
1035
                                GridLengthEditor source = e.Data.GetData(typeof(GridLengthEditor)) as GridLengthEditor;
 
1036
                                e.Handled = true;
 
1037
                                
 
1038
                                if (marker != null) {
 
1039
                                        AdornerLayer.GetAdornerLayer(marker.AdornedElement).Remove(marker);
 
1040
                                        marker = null;
 
1041
                                }
 
1042
                                
 
1043
                                if (target != null && source != null && source.Orientation == Orientation.Vertical && source.Cell + 1 < rowDefitions.Elements().Count()) {
 
1044
                                        marker = DragDropMarkerAdorner.CreateAdornerCellMove(target);
 
1045
                                        e.Effects = DragDropEffects.Move;
 
1046
                                        return;
 
1047
                                }
 
1048
                                
 
1049
                                e.Effects = DragDropEffects.None;
 
1050
                        } catch (Exception ex) {
 
1051
                                Core.LoggingService.Error(ex);
 
1052
                        }
 
1053
                }
 
1054
        }
 
1055
}