-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathClsPCB.vb
1197 lines (1081 loc) · 47.1 KB
/
ClsPCB.vb
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Imports System.Collections.ObjectModel
Imports System.IO
Public Class PCB
Private Class EagleLibraryComparer
Implements IComparer(Of Eagle.Project)
Public Function Compare(ByVal x As Eagle.Project, ByVal y As Eagle.Project) As Integer Implements System.Collections.Generic.IComparer(Of Eagle.Project).Compare
Return StrComp(x.ShortFileName, y.ShortFileName, CompareMethod.Text)
End Function
End Class
Public Structure WindowSetting
Dim HorizontalMirror As Boolean
Dim VerticalMirror As Boolean
End Structure
Public Enum WindowTypes As Integer
WindowTypeTop = 0
WindowTypeBottom = 1
End Enum
Public Enum LayerTypes As Integer
LayerTypeTopImage = 0
LayerTypeBottomImage = 1
LayerTypeTopPads = 2
LayerTypeBottomPads = 3
LayerTypeTopInfo = 4
LayerTypeBottomInfo = 5
LayerTypeTopDevice = 6
LayerTypeBottomDevice = 7
LayerTypeTopDrawing = 8 'these m_layers are used for temporary drawing some objects for animation of the cursor
LayerTypeBottomDrawing = 9
LayerTypeTopVias = 10
LayerTypeBottomVias = 11
LayerTypeTopRoute = 12
LayerTypeBottomRoute = 13
End Enum
Public Const MAX_UNDOREDO_SIZE As Integer = 30
Protected m_Layers As New ExtentedDictionary(Of LayerTypes, Layer) 'holds the layers
Protected m_LayerObjects As New ExtentedDictionary(Of Integer, LayerObject) 'all objects on the m_layers
Protected m_Devices As New ExtentedDictionary(Of String, Device) 'all Devices (ICs, resistors)
Protected m_Libraries As New List(Of Eagle.Project) 'loaded eagle m_Libraries
Protected m_ConnectionMatrix As New ConnectionMatrix(Me) 'connections between pads
Protected m_UndoStack As New LinkedList(Of UndoRedoItem) 'all things that can be undone
Protected m_RedoStack As New Stack(Of UndoRedoItem)(MAX_UNDOREDO_SIZE) 'all things that have been undone and can now be redone
Protected m_Schematic As PCBSchematic
Protected m_SelectedObjects As New ExtentedDictionary(Of Integer, SelectableLayerObject) 'all objects that are selected at this moment
Protected m_HighLightedObjects As New ExtentedDictionary(Of Integer, SelectableLayerObject) 'all objects that are highlighted at this moment
Protected m_Width As Single 'width of the PCB in pixels
Protected m_Height As Single 'height of the PCB in pixels, the images must have both the same size
Protected m_Name As String 'name of the project
Protected m_Cursor As System.Windows.Forms.Cursor
Protected m_WindowSettings() As WindowSetting
Protected m_isChanged As Boolean
Protected m_FileName As String
Public Event SizeChanged(ByVal Sender As PCB, ByVal Width As Single, ByVal Height As Single) 'fired when size of pcb has changed
Public Event UpdateGraphics(ByVal Sender As PCB, ByVal WindowType As WindowTypes) 'fired when the graphics must be updated on a window
Public Event ChangeCursor(ByVal Sender As PCB, ByVal Cursor As System.Windows.Forms.Cursor)
Public Event DeviceAdded(ByVal Sender As PCB, ByVal Device As Device)
Public Event DeviceRemoved(ByVal Sender As PCB, ByVal Device As Device)
Public Event DeviceNameChangedEvent(ByVal Sender As PCB, ByVal Device As Device, ByVal OldName As String, ByVal NewName As String)
Public Event NameChanged(ByVal Sender As PCB, ByVal Name As String)
Public Event UndoRedoAction(ByVal Sender As PCB, ByVal UndoRedoItem As UndoRedoItem, ByVal Undo As Boolean) 'raised when something is undone / redone, if undone the undo is set to true
Public Event UndoRedoStackUpdate(ByVal Sender As PCB, ByVal UndoStack As LinkedList(Of UndoRedoItem), ByVal RedoStack As Stack(Of UndoRedoItem)) 'if the undo/redo stack was updated
Public Event ProjectChanged(ByVal Sender As PCB) 'fired if any changed made
Public Event ProjectLoaded(ByVal Sender As PCB, ByVal ZipFile As Ionic.Zip.ZipFile)
Public Event ProjectSaved(ByVal Sender As PCB, ByVal ZipFile As Ionic.Zip.ZipFile)
Public Event ObjectsSelected(ByVal Sender As PCB, ByVal Objects As List(Of SelectableLayerObject))
Public Event ObjectsDeselected(ByVal Sender As PCB, ByVal Objects As List(Of SelectableLayerObject))
Public Event ObjectsHighlighted(ByVal Sender As PCB, ByVal Objects As List(Of SelectableLayerObject))
Public Event ObjectsDeHighlighted(ByVal Sender As PCB, ByVal Objects As List(Of SelectableLayerObject))
Public Event ObjectNameChangedEvent(ByVal Sender As PCB, ByVal LayerObject As LayerObject, ByVal OldName As String, ByVal NewName As String)
Public Event ObjectsLoaded(ByVal Sender As PCB, ByVal Root As Xml.XmlNode, ByVal BinData As Ionic.Zip.ZipFile) 'fired after loading of document completed and all objects have been assigned
Public Event BackgroundImageMirrorChanged(ByVal Sender As PCB, ByVal WIndowType As WindowTypes, ByVal VerticalMirrorChanged As Boolean)
Public Event LayerVisibilityChanged(ByVal Sender As PCB, ByVal Layer As Layer, ByVal Visible As Boolean)
'sets up a new unpcb project, creates top and bottom window and adds some default m_layers to them
Public Sub New()
Dim Layer_Types As Array = System.Enum.GetValues(GetType(LayerTypes))
Dim Layer_Type As LayerTypes
m_Schematic = New PCBSchematic(Me)
For Each Layer_Type In Layer_Types
Dim Layer As Layer = New Layer(Layer_Type)
m_Layers.Add(Layer_Type, Layer)
AddHandler Layer.LayerVisibilityChanged, AddressOf LayerVisibilityHasChanged
Next
ReDim m_WindowSettings(0 To 1)
IsChanged = False
End Sub
Protected Sub LayerVisibilityHasChanged(ByVal Layer As Layer, ByVal Visible As Boolean)
RaiseEvent LayerVisibilityChanged(Me, Layer, Visible)
End Sub
''' <summary>
''' Returns the last saved file name, empty if not yet saved
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property FileName() As String
Get
Return m_FileName
End Get
End Property
''' <summary>
''' Returns if this PCB project was changed
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property IsChanged() As Boolean
Get
Return m_isChanged
End Get
Set(ByVal value As Boolean)
m_isChanged = value
RaiseEvent ProjectChanged(Me)
End Set
End Property
''' <summary>
''' Returns all the layers as a dictionary
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property Layers() As ReadOnlyDictionary(Of LayerTypes, Layer)
Get
Return m_Layers.GetReadonlyDictionary()
End Get
End Property
''' <summary>
''' Returns all the objects which can be located at one or more layers
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property LayerObjects() As ReadOnlyDictionary(Of Integer, LayerObject)
Get
Return m_LayerObjects.GetReadonlyDictionary()
End Get
End Property
''' <summary>
''' Returns all the devices that were soldered on the PCB
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property Devices() As ReadOnlyDictionary(Of String, Device)
Get
Return m_Devices.GetReadonlyDictionary()
End Get
End Property
''' <summary>
''' Returns all eagle libraries
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property Libraries() As ReadOnlyCollection(Of Eagle.Project)
Get
Return m_Libraries.AsReadOnly()
End Get
End Property
''' <summary>
''' Returns the connections between pads and vias
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property ConnectionMatrix() As ConnectionMatrix
Get
Return m_ConnectionMatrix
End Get
End Property
''' <summary>
''' Returns all undo actions
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property UndoStack() As LinkedList(Of UndoRedoItem)
Get
Return m_UndoStack
End Get
End Property
''' <summary>
''' Returns all redo actions
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property RedoStack() As Stack(Of UndoRedoItem)
Get
Return m_RedoStack
End Get
End Property
''' <summary>
''' Returns the schematic
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public ReadOnly Property Schematic() As PCBSchematic
Get
Return m_Schematic
End Get
End Property
''' <summary>
''' Gets / sets the project name
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Name() As String
Get
Return m_Name
End Get
Set(ByVal value As String)
m_Name = value
RaiseEvent NameChanged(Me, value)
End Set
End Property
''' <summary>
''' Returns the width of the processed PCB image
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Width() As Long
Get
Return m_Width
End Get
Set(ByVal value As Long)
m_Width = value
RaiseEvent SizeChanged(Me, m_Width, m_Height)
End Set
End Property
''' <summary>
''' Returns the height in pixels of the processed PCB image
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Height() As Long
Get
Return m_Height
End Get
Set(ByVal value As Long)
m_Height = value
RaiseEvent SizeChanged(Me, m_Width, m_Height)
End Set
End Property
''' <summary>
''' Returns the window type for a given layertype (says if the layer is on bottom or top layer window)
''' </summary>
''' <param name="LayerType"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetWindowTypeOfLayerType(ByVal LayerType As LayerTypes) As WindowTypes
If (LayerType Mod 2) <> 0 Then
Return WindowTypes.WindowTypeBottom
Else
Return WindowTypes.WindowTypeTop
End If
End Function
''' <summary>
''' Returns a layer based on it's layer type
''' </summary>
''' <param name="LayerType"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetLayer(ByVal LayerType As LayerTypes) As Layer
Return m_Layers(LayerType)
End Function
''' <summary>
''' Returns a layerobject based on it's ID
''' </summary>
''' <param name="Id"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetLayerObject(ByVal Id As Integer) As LayerObject
If m_LayerObjects.ContainsKey(Id) Then
Return m_LayerObjects(Id)
End If
Return Nothing
End Function
''' <summary>
''' Returns the layer object by it's name
''' </summary>
''' <param name="Name"></param>
''' <returns>LayerObject</returns>
''' <remarks>Returns nothing if name doesn't exist</remarks>
Public Function GetLayerObject(ByVal Name As String) As LayerObject
For Each LayerObject As KeyValuePair(Of Integer, LayerObject) In m_LayerObjects
If StrComp(LayerObject.Value.Name, Name, CompareMethod.Text) = 0 Then
Return LayerObject.Value
End If
Next
Return Nothing
End Function
''' <summary>
''' Returns if an object with Name already exists in the collection
''' </summary>
''' <param name="Name">The name to check</param>
''' <param name="ExcludeId">Exclude this object id from the search</param>
''' <returns></returns>
''' <remarks></remarks>
Public Function LayerObjectNameExists(ByVal Name As String, Optional ByVal ExcludeId As Integer = -1) As Boolean
Dim Obj As LayerObject = GetLayerObject(Name)
If Obj IsNot Nothing Then
Return Obj.id <> ExcludeId
End If
Return False
End Function
''' <summary>
''' Returns all the currently selected layer objects
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetSelectedLayerObjects() As ReadOnlyDictionary(Of Integer, SelectableLayerObject)
Return m_SelectedObjects.GetReadonlyDictionary()
End Function
''' <summary>
''' Returns all the currently selected layer objects of a certain object type
''' </summary>
''' <param name="ObjectType"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetSelectedLayerObjects(ByVal ObjectType As Type) As List(Of SelectableLayerObject)
Dim SelectedObjects As New List(Of SelectableLayerObject)
For Each LayerObject As KeyValuePair(Of Integer, LayerObject) In m_LayerObjects
If LayerObject.Value.GetType().IsSubclassOf(ObjectType) Then
If CType(LayerObject.Value, SelectableLayerObject).Selected Then
SelectedObjects.Add(LayerObject.Value)
End If
End If
Next
Return SelectedObjects
End Function
''' <summary>
''' Connects all selected pads
''' </summary>
''' <remarks></remarks>
Public Sub ConnectSelectedPads()
Dim Selected As List(Of SelectableLayerObject) = GetSelectedLayerObjects(GetType(Pad))
m_ConnectionMatrix.ConnectPads(Array.ConvertAll(Selected.ToArray(), New Converter(Of SelectableLayerObject, Pad)(AddressOf CastPad)))
DeselectAllObjects()
End Sub
''' <summary>
''' Disconnects all selected pads
''' </summary>
''' <remarks></remarks>
Public Sub DisconnectSelectedPads()
Dim Selected As List(Of SelectableLayerObject) = GetSelectedLayerObjects(GetType(Pad))
m_ConnectionMatrix.DisconnectPads(Array.ConvertAll(Selected.ToArray(), New Converter(Of SelectableLayerObject, Pad)(AddressOf CastPad)))
DeselectAllObjects()
End Sub
''' <summary>
''' Selected pads will never be connected
''' </summary>
''' <remarks></remarks>
Public Sub NOTConnectSelectedPads()
Dim Selected As List(Of SelectableLayerObject) = GetSelectedLayerObjects(GetType(Pad))
m_ConnectionMatrix.NotConnectPads(Array.ConvertAll(Selected.ToArray(), New Converter(Of SelectableLayerObject, Pad)(AddressOf CastPad)))
DeselectAllObjects()
End Sub
''' <summary>
''' The selected pad(s) will never be connected to unselected pads which have unknown connection state
''' </summary>
''' <remarks></remarks>
Public Sub NOTConnectSelectedPadsToAllPads()
Dim Selected As List(Of SelectableLayerObject) = GetSelectedLayerObjects(GetType(Pad))
If Selected.Count > 0 Then
Dim PPad As Pad = Nothing
For Each SelectedObject As SelectableLayerObject In Selected
If PPad IsNot Nothing Then
m_ConnectionMatrix.ConnectPads(PPad, CType(SelectedObject, Pad))
End If
PPad = CType(SelectedObject, Pad)
Next
m_ConnectionMatrix.NotConnectToAllPads(CType(Selected(0), Pad))
End If
DeselectAllObjects()
End Sub
''' <summary>
''' Creates undo information and removes object from the project
''' </summary>
''' <param name="LayerObject"></param>
''' <remarks></remarks>
Public Sub DeleteObject(ByVal LayerObject As LayerObject)
AddUndoItem(LayerObject.GetUndoDeleteItem(Me))
RemoveObject(LayerObject)
End Sub
''' <summary>
''' Removes object from the project without saving undo information
''' </summary>
''' <param name="LayerObject"></param>
''' <remarks></remarks>
Public Sub RemoveObject(ByVal LayerObject As LayerObject)
LayerObject.Remove()
m_LayerObjects.Remove(LayerObject.id)
End Sub
''' <summary>
''' Returns eagle library project by it's name
''' </summary>
''' <param name="Name"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetEagleLibraryByName(ByVal Name As String) As Eagle.Project
For Each Library As Eagle.Project In m_Libraries
If Library.Drawing.Library.Name = Name Then
Return Library
End If
Next
Return Nothing
End Function
''' <summary>
''' Returns an eagle project with ShortFileName
''' </summary>
''' <param name="ShortFileName"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetEagleLibrary(ByVal ShortFileName As String) As Eagle.Project
For Each Library As Eagle.Project In m_Libraries
If Library.ShortFileName = ShortFileName Then
Return Library
End If
Next
Return Nothing
End Function
''' <summary>
''' Adds an eagle library to the collection
''' </summary>
''' <param name="Library"></param>
''' <returns>True if success</returns>
''' <remarks></remarks>
Public Function AddEagleLibrary(ByVal Library As Eagle.Project)
If GetEagleLibrary(Library.ShortFileName) Is Nothing Then
m_Libraries.Add(Library)
Return True
End If
Return False
End Function
''' <summary>
''' Sorts the Eagle libraries alphabetically
''' </summary>
''' <remarks></remarks>
Public Sub SortEagleLibraries()
m_Libraries.Sort(New EagleLibraryComparer)
End Sub
''' <summary>
''' Loads a new Eagle library
''' </summary>
''' <param name="FileName"></param>
''' <remarks></remarks>
Public Function LoadEagleLibrary(ByVal FileName As String) As Boolean
Dim Project As New Eagle.Project()
If Project.Load(FileName) Then
Return AddEagleLibrary(Project)
End If
Return False
End Function
''' <summary>
''' Tries to unload an eagle library, returns false if library is in use
''' </summary>
''' <param name="ShortFilename"></param>
''' <returns></returns>
''' <remarks>must save undo item when removing, because the library may still be used by removed devices in the undo/redo list</remarks>
Public Function RemoveEagleLibrary(ByVal ShortFilename As String) As Boolean
Dim Library As Eagle.Project = GetEagleLibrary(ShortFilename)
If Not IsEagleLibraryInUse(Library) Then
m_Libraries.Remove(Library)
Return True
End If
Return False
End Function
''' <summary>
''' Returns true if a library is still in use in this project
''' </summary>
''' <param name="Library"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function IsEagleLibraryInUse(ByVal Library As Eagle.Project) As Boolean
If Library IsNot Nothing Then
For Each Device As KeyValuePair(Of String, Device) In m_Devices
If Device.Value.EagleDevice.DeviceSet.Library.Drawing.Project.Equals(Library) Then
Return True
End If
Next
End If
Return False
End Function
''' <summary>
''' Tries to update a used eagle library
''' </summary>
''' <param name="FileName"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function UpdateEagleLibrary(ByVal FileName As String) As Boolean
MsgBox("To be implemented")
End Function
'Called when an objects name was changed
Private Sub ObjectNameChanged(ByVal Sender As LayerObject, ByVal OldName As String, ByRef NewName As String)
If OldName <> NewName Then
If LayerObjectNameExists(NewName) Then
Throw New NameExistsException("An object with this name already exists!")
End If
RaiseEvent ObjectNameChangedEvent(Me, Sender, OldName, NewName)
End If
End Sub
''' <summary>
''' Adds a layer object to the object collection without placing it on one of the m_layers
''' </summary>
''' <param name="LayerObject"></param>
''' <remarks></remarks>
Public Function AddObject(ByVal LayerObject As LayerObject) As LayerObject
If LayerObjectNameExists(LayerObject.Name) Then
Throw New NameExistsException("An object with this name already exists!")
End If
m_LayerObjects.Add(LayerObject.id, LayerObject)
LayerObject.AddToPCB(Me)
AddHandler LayerObject.NameChanged, AddressOf ObjectNameChanged
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
Return LayerObject
End Function
''' <summary>
''' Places / adds a layerobject on a window at it's current location (depending on the window type it will be placed on its top or bottom layer)
''' </summary>
''' <param name="Obj"></param>
''' <param name="WindowType"></param>
''' <remarks></remarks>
Public Sub PlaceObject(ByVal Obj As LayerObject, ByVal WindowType As PCB.WindowTypes)
AddUndoItem(Obj.GetUndoAddItem(Me))
Obj.PlaceObject(Me, WindowType)
AddObject(Obj)
End Sub
''' <summary>
''' Places / adds a layerobject on a window at Location (depending on the window type it will be placed on its top or bottom layer) fires updategraphics event
''' </summary>
''' <param name="Obj"></param>
''' <param name="WindowType"></param>
''' <param name="Location"></param>
''' <remarks>Also saves undo item</remarks>
Public Sub PlaceObject(ByVal Obj As LayerObject, ByVal WindowType As PCB.WindowTypes, ByVal Location As Point)
AddUndoItem(Obj.GetUndoAddItem(Me))
Obj.PlaceObject(Me, WindowType, Location)
AddObject(Obj)
End Sub
''' <summary>
''' Checks is a device with Name already exists in the collection
''' </summary>
''' <param name="Name"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function DeviceNameExists(ByVal Name As String) As Boolean
Return m_Devices.ContainsKey(Name)
End Function
''' <summary>
''' Adds a device to the m_Devices collection and fires an event that the list has changed
''' If the device has any pins / pads they will also be added to the project if not yet added
''' </summary>
''' <param name="Device"></param>
''' <remarks></remarks>
Public Function AddDevice(ByVal Device As Device) As Device
If DeviceNameExists(Device.Name) Then
Throw New NameExistsException("A device with this name already exists.")
End If
m_Devices.Add(Device.Name, Device)
For Each DevicePin As DevicePin In Device.Pins
For Each Pad As Pad In DevicePin.Pads
If GetLayerObject(Pad.id) Is Nothing Then
PlaceObject(Pad, Pad.WindowType) 'adds the pad and places it back on the correct layer
End If
For Each Route As Route In Pad.Routes
If GetLayerObject(Route.id) Is Nothing Then
PlaceObject(Route, Route.WindowType) 'add all routes connect to the pads to the correct layer
End If
'Route.StartPad.Routes.Add(Route)
'Route.EndPad.Routes.Add(Route)
For Each RoutePoint As RoutePoint In Route.RoutePoints
If GetLayerObject(RoutePoint.id) Is Nothing Then
PlaceObject(RoutePoint, RoutePoint.WindowType)
End If
Next
Next
Next
Next
AddHandler Device.NameChanged, AddressOf DeviceNameChanged
RaiseEvent DeviceAdded(Me, Device)
Return Device
End Function
'called when the device name is changed
Private Sub DeviceNameChanged(ByVal Sender As Device, ByVal OldName As String, ByRef NewName As String)
If OldName <> NewName Then
If m_Devices.ContainsKey(NewName) Then
Throw New NameExistsException("The new device name already exists")
Else
m_Devices.Remove(OldName)
m_Devices.Add(NewName, Sender)
End If
RaiseEvent DeviceNameChangedEvent(Me, Sender, OldName, NewName)
End If
End Sub
''' <summary>
''' Returns a new unique device name for a certain prefix
''' </summary>
''' <param name="Prefix"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetUniqueDeviceName(ByVal Prefix As String)
Dim Cnt As Integer = 1
Dim Max As Integer = 0
Dim DeviceNumber As Integer
If Prefix = "" Then Prefix = "U"
For Each DeviceName As String In m_Devices.Keys
If Mid(DeviceName, 1, Prefix.Length) = Prefix Then
If Integer.TryParse(Mid(DeviceName, Prefix.Length + 1), DeviceNumber) Then
Max = Math.Max(Max, DeviceNumber)
End If
Cnt += 1
End If
Next
Return Prefix & Math.Max(Max + 1, Cnt)
End Function
''' <summary>
''' Removes a device object from the project and it's connected pads wihtout saving undo information
''' </summary>
''' <param name="Device"></param>
''' <remarks></remarks>
Public Sub RemoveDevice(ByVal Device As Device)
If m_Devices.ContainsKey(Device.Name) Then
Device.Remove()
End If
m_Devices.Remove(Device.Name)
RemoveHandler Device.NameChanged, AddressOf DeviceNameChanged
RaiseEvent DeviceRemoved(Me, Device)
End Sub
''' <summary>
''' Deselects all objects
''' </summary>
''' <remarks></remarks>
Public Sub DeselectAllObjects()
Dim SelectableLayerObject As SelectableLayerObject
Dim SelectedObjects As New List(Of SelectableLayerObject)
For Each LayerObject As KeyValuePair(Of Integer, LayerObject) In m_LayerObjects
If TypeOf LayerObject.Value Is SelectableLayerObject Then
SelectableLayerObject = CType(LayerObject.Value, SelectableLayerObject)
SelectableLayerObject.Selected = False
'SelectedObjects.Add(SelectableLayerObject)
End If
Next
m_SelectedObjects.Clear()
RaiseEvent ObjectsDeselected(Me, SelectedObjects)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
End Sub
''' <summary>
''' Returns all objects that are highlighted
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetHighlightedObjects() As ReadOnlyDictionary(Of Integer, SelectableLayerObject)
Return m_HighLightedObjects.GetReadonlyDictionary()
End Function
''' <summary>
''' Removes the highlight from all objects, fires updategraphics event
''' </summary>
''' <param name="NoGraphicsUpdate">If set to true the UpdateGraphics event is not fired</param>
''' <remarks></remarks>
Public Sub UnHighlightAllObjects(Optional ByVal NoGraphicsUpdate As Boolean = False)
Dim HighlightedObjects As New List(Of SelectableLayerObject)
For Each HighlightedObject As KeyValuePair(Of Integer, SelectableLayerObject) In m_HighLightedObjects
HighlightedObject.Value.Highlighted = False
HighlightedObjects.Add(HighlightedObject.Value)
Next
m_HighLightedObjects.Clear()
RaiseEvent ObjectsDeHighlighted(Me, HighlightedObjects)
If Not NoGraphicsUpdate Then
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
End If
End Sub
''' <summary>
''' Removes the highlight from the layerobject, fires update graphics event
''' </summary>
''' <param name="LayerObject"></param>
''' <remarks></remarks>
Public Sub UnHighlightObject(ByVal LayerObject As SelectableLayerObject)
Dim LayerObjects As New List(Of SelectableLayerObject)
LayerObjects.Add(LayerObject)
LayerObject.Highlighted = False
If m_HighLightedObjects.ContainsKey(LayerObject.id) Then m_HighLightedObjects.Remove(LayerObject.id)
RaiseEvent ObjectsDeHighlighted(Me, LayerObjects)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
End Sub
''' <summary>
''' Highlights an object and fires the updategraphics event
''' </summary>
''' <param name="LayerObject"></param>
''' <remarks></remarks>
Public Sub HighlightObject(ByVal LayerObject As SelectableLayerObject)
Dim LayerObjects As New List(Of SelectableLayerObject)
If Not LayerObject.Highlighted Then LayerObjects.Add(LayerObject)
LayerObject.Highlighted = True
If Not m_HighLightedObjects.ContainsKey(LayerObject.id) Then m_HighLightedObjects.Add(LayerObject.id, LayerObject)
RaiseEvent ObjectsHighlighted(Me, LayerObjects)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
End Sub
''' <summary>
''' Selects an object and fires updategraphics event
''' </summary>
''' <param name="LayerObject"></param>
''' <remarks></remarks>
Public Sub SelectObject(ByVal LayerObject As SelectableLayerObject)
Dim LayerObjects As New List(Of SelectableLayerObject)
If Not LayerObject.Selected Then LayerObjects.Add(LayerObject)
LayerObject.Selected = True
If Not m_SelectedObjects.ContainsKey(LayerObject.id) Then m_SelectedObjects.Add(LayerObject.id, LayerObject)
RaiseEvent ObjectsSelected(Me, LayerObjects)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
End Sub
''' <summary>
''' Selects all objects from the given array and fires events to update graphics
''' </summary>
''' <param name="LayerObjects"></param>
''' <remarks></remarks>
Public Sub SelectObject(ByVal LayerObjects() As SelectableLayerObject)
Dim Objects As New List(Of SelectableLayerObject)
For Each obj As SelectableLayerObject In LayerObjects
If Not obj.Selected Then Objects.Add(obj)
obj.Selected = True
If Not m_SelectedObjects.ContainsKey(obj.id) Then m_SelectedObjects.Add(obj.id, obj)
Next
RaiseEvent ObjectsSelected(Me, Objects)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
End Sub
''' <summary>
''' Returns the closest object on Windowtype in objecttypes located in a max distance
''' </summary>
''' <param name="WindowType"></param>
''' <param name="Point"></param>
''' <param name="ObjectTypes"></param>
''' <param name="maxDistance"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetClosestObject(ByVal WindowType As WindowTypes, ByVal Point As PointF, ByVal ObjectTypes As List(Of Type), Optional ByVal maxDistance As Single = Single.MaxValue, Optional ByVal ExcludeObject As LayerObject = Nothing) As LayerObject
Dim TmpDistance As Single
Dim Distance As Single
Dim ObjectFound As LayerObject = Nothing
Distance = Single.MaxValue
For Each Layer As KeyValuePair(Of LayerTypes, Layer) In m_Layers
If GetWindowTypeOfLayerType(Layer.Key) = WindowType Then
For Each LayerObject As LayerObject In Layer.Value.LayerObjects
If ObjectTypes.Contains(LayerObject.GetType) Then
If ExcludeObject Is Nothing OrElse Not LayerObject.Equals(ExcludeObject) Then
TmpDistance = LayerObject.GetDistance(Point)
If TmpDistance < Distance Then
Distance = TmpDistance
ObjectFound = LayerObject
End If
End If
End If
Next
End If
Next
If Distance <= maxDistance Then
Return ObjectFound
End If
Return Nothing
End Function
''' <summary>
''' Selects the object closest to the point and returns this object or nothing if there are no objects there
''' </summary>
''' <param name="WindowType"></param>
''' <param name="Point"></param>
''' <param name="MultiSelect"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SelectObjects(ByVal WindowType As WindowTypes, ByVal Point As PointF, Optional ByVal MultiSelect As Boolean = False) As LayerObject
Dim LayerObject As LayerObject, SelectableLayerObject As SelectableLayerObject
Dim ClosestObject As SelectableLayerObject = Nothing, Distance As Single
Dim TmpDistance As Single
If Not MultiSelect Then
DeselectAllObjects()
End If
Distance = Single.MaxValue
For Each Layer As KeyValuePair(Of LayerTypes, Layer) In m_Layers
If Layer.Value.Visible AndAlso GetWindowTypeOfLayerType(Layer.Key) = WindowType Then
For Each LayerObject In Layer.Value.LayerObjects
If TypeOf LayerObject Is SelectableLayerObject Then
SelectableLayerObject = CType(LayerObject, SelectableLayerObject)
If SelectableLayerObject.Visible Then
TmpDistance = SelectableLayerObject.GetDistance(Point) ' Functions.Distance(Point, SelectableLayerObject.Center)
If TmpDistance < Distance Then
ClosestObject = SelectableLayerObject
Distance = TmpDistance
End If
End If
End If
Next
End If
Next
If Not ClosestObject Is Nothing Then
SelectObject(ClosestObject)
End If
Return ClosestObject
End Function
''' <summary>
''' Returns the cursor that should be used on the windows and raises the changecursur event on case of an update
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Cursor()
Get
Return m_Cursor
End Get
Set(ByVal value)
m_Cursor = value
RaiseEvent ChangeCursor(Me, value)
End Set
End Property
''' <summary>
''' Gets / Sets if the PCB image should be mirrored horizontally for the specified window
''' </summary>
''' <param name="WindowType"></param>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property HorizontalMirror(ByVal WindowType As WindowTypes) As Boolean
Get
Return m_WindowSettings(WindowType).HorizontalMirror
End Get
Set(ByVal value As Boolean)
m_WindowSettings(WindowType).HorizontalMirror = value
RaiseEvent BackgroundImageMirrorChanged(Me, WindowType, False)
RaiseEvent UpdateGraphics(Me, WindowType)
End Set
End Property
''' <summary>
''' Gets / Sets if the PCB image should be mirrored vertically for the specified window
''' </summary>
''' <param name="WindowType"></param>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property VerticalMirror(ByVal WindowType As WindowTypes) As Boolean
Get
Return m_WindowSettings(WindowType).VerticalMirror
End Get
Set(ByVal value As Boolean)
m_WindowSettings(WindowType).VerticalMirror = value
RaiseEvent BackgroundImageMirrorChanged(Me, WindowType, True)
RaiseEvent UpdateGraphics(Me, WindowType)
End Set
End Property
''' <summary>
''' Add new undo action to the undo stack
''' </summary>
''' <param name="UndoItem"></param>
''' <remarks></remarks>
Public Function AddUndoItem(ByVal UndoItem As UndoRedoItem) As UndoRedoItem
m_UndoStack.AddFirst(UndoItem)
m_RedoStack.Clear()
If m_UndoStack.Count() > MAX_UNDOREDO_SIZE Then
m_UndoStack.RemoveLast()
End If
RaiseEvent UndoRedoStackUpdate(Me, m_UndoStack, m_RedoStack)
Return UndoItem
End Function
''' <summary>
''' Undo the last command
''' </summary>
''' <remarks></remarks>
Public Sub Undo()
Dim UndoItem As UndoRedoItem = m_UndoStack.First().Value
m_UndoStack.RemoveFirst()
UndoItem.Undo()
m_RedoStack.Push(UndoItem)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UndoRedoAction(Me, UndoItem, True)
RaiseEvent UndoRedoStackUpdate(Me, m_UndoStack, m_RedoStack)
End Sub
''' <summary>
''' Redo the last command
''' </summary>
''' <remarks></remarks>
Public Sub Redo()
Dim RedoItem As UndoRedoItem = m_RedoStack.Pop()
RedoItem.Redo()
m_UndoStack.AddFirst(RedoItem)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeBottom)
RaiseEvent UpdateGraphics(Me, WindowTypes.WindowTypeTop)
RaiseEvent UndoRedoAction(Me, RedoItem, False)
RaiseEvent UndoRedoStackUpdate(Me, m_UndoStack, m_RedoStack)
End Sub
''' <summary>
''' Saves the PCB project to an XMLDoc and zip file (for binary data part)
''' </summary>
''' <param name="XMLDoc"></param>
''' <param name="Root"></param>
''' <param name="BinData"></param>
''' <remarks></remarks>
Public Sub toXML(ByVal XMLDoc As Xml.XmlDocument, ByVal Root As Xml.XmlNode, ByVal BinData As Ionic.Zip.ZipFile)
Dim WindowRoot As Xml.XmlElement
Dim WindowNode As Xml.XmlElement
Dim LayerRoot As Xml.XmlElement
Dim LayerObjectRoot As Xml.XmlElement
Dim ConnectionRoot As Xml.XmlElement
Dim DevicesRoot As Xml.XmlElement
Dim SchematicRoot As Xml.XmlElement
Root.Attributes.Append(XMLDoc.CreateAttribute("name")).Value = m_Name
Root.Attributes.Append(XMLDoc.CreateAttribute("width")).Value = SingleToString(m_Width)
Root.Attributes.Append(XMLDoc.CreateAttribute("height")).Value = SingleToString(m_Height)
WindowRoot = Root.AppendChild(XMLDoc.CreateElement("windows"))
Dim Window_Types As Array = System.Enum.GetValues(GetType(WindowTypes))
For Each Window_type As WindowTypes In Window_Types
WindowNode = WindowRoot.AppendChild(XMLDoc.CreateElement("window"))