mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-27 06:51:37 -04:00
refactoring of library system to allow separate component tree view
This commit is contained in:
parent
84b16602de
commit
6dc25b04ea
@ -122,7 +122,7 @@ Single-Cycle CPU.</string>
|
|||||||
<boolean>true</boolean>
|
<boolean>true</boolean>
|
||||||
</entry>
|
</entry>
|
||||||
</elementAttributes>
|
</elementAttributes>
|
||||||
<pos x="1220" y="40"/>
|
<pos x="1180" y="40"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Branch.dig</elementName>
|
<elementName>Branch.dig</elementName>
|
||||||
@ -188,6 +188,10 @@ Single-Cycle CPU.</string>
|
|||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Driver</elementName>
|
<elementName>Driver</elementName>
|
||||||
<elementAttributes>
|
<elementAttributes>
|
||||||
|
<entry>
|
||||||
|
<string>rotation</string>
|
||||||
|
<rotation rotation="1"/>
|
||||||
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<string>Bits</string>
|
<string>Bits</string>
|
||||||
<int>16</int>
|
<int>16</int>
|
||||||
@ -197,12 +201,12 @@ Single-Cycle CPU.</string>
|
|||||||
<boolean>true</boolean>
|
<boolean>true</boolean>
|
||||||
</entry>
|
</entry>
|
||||||
</elementAttributes>
|
</elementAttributes>
|
||||||
<pos x="520" y="120"/>
|
<pos x="520" y="40"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>PC.dig</elementName>
|
<elementName>PC.dig</elementName>
|
||||||
<elementAttributes/>
|
<elementAttributes/>
|
||||||
<pos x="360" y="120"/>
|
<pos x="400" y="120"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Clock</elementName>
|
<elementName>Clock</elementName>
|
||||||
@ -477,16 +481,12 @@ Single-Cycle CPU.</string>
|
|||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Tunnel</elementName>
|
<elementName>Tunnel</elementName>
|
||||||
<elementAttributes>
|
<elementAttributes>
|
||||||
<entry>
|
|
||||||
<string>rotation</string>
|
|
||||||
<rotation rotation="3"/>
|
|
||||||
</entry>
|
|
||||||
<entry>
|
<entry>
|
||||||
<string>NetName</string>
|
<string>NetName</string>
|
||||||
<string>stPC</string>
|
<string>stPC</string>
|
||||||
</entry>
|
</entry>
|
||||||
</elementAttributes>
|
</elementAttributes>
|
||||||
<pos x="520" y="160"/>
|
<pos x="560" y="40"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Tunnel</elementName>
|
<elementName>Tunnel</elementName>
|
||||||
@ -528,7 +528,7 @@ Single-Cycle CPU.</string>
|
|||||||
<string>abs</string>
|
<string>abs</string>
|
||||||
</entry>
|
</entry>
|
||||||
</elementAttributes>
|
</elementAttributes>
|
||||||
<pos x="340" y="160"/>
|
<pos x="380" y="160"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Tunnel</elementName>
|
<elementName>Tunnel</elementName>
|
||||||
@ -576,7 +576,7 @@ Single-Cycle CPU.</string>
|
|||||||
<string>ALU2D</string>
|
<string>ALU2D</string>
|
||||||
</entry>
|
</entry>
|
||||||
</elementAttributes>
|
</elementAttributes>
|
||||||
<pos x="1260" y="40"/>
|
<pos x="1220" y="40"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Tunnel</elementName>
|
<elementName>Tunnel</elementName>
|
||||||
@ -662,7 +662,7 @@ Single-Cycle CPU.</string>
|
|||||||
<string>C</string>
|
<string>C</string>
|
||||||
</entry>
|
</entry>
|
||||||
</elementAttributes>
|
</elementAttributes>
|
||||||
<pos x="340" y="140"/>
|
<pos x="380" y="140"/>
|
||||||
</visualElement>
|
</visualElement>
|
||||||
<visualElement>
|
<visualElement>
|
||||||
<elementName>Tunnel</elementName>
|
<elementName>Tunnel</elementName>
|
||||||
@ -766,7 +766,7 @@ Single-Cycle CPU.</string>
|
|||||||
</visualElements>
|
</visualElements>
|
||||||
<wires>
|
<wires>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="340" y="320"/>
|
<p1 x="380" y="320"/>
|
||||||
<p2 x="940" y="320"/>
|
<p2 x="940" y="320"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
@ -782,16 +782,20 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="1360" y="320"/>
|
<p2 x="1360" y="320"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="600" y="0"/>
|
<p1 x="520" y="0"/>
|
||||||
|
<p2 x="640" y="0"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="640" y="0"/>
|
||||||
<p2 x="800" y="0"/>
|
<p2 x="800" y="0"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1220" y="0"/>
|
<p1 x="800" y="0"/>
|
||||||
<p2 x="1440" y="0"/>
|
<p2 x="1180" y="0"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="800" y="0"/>
|
<p1 x="1180" y="0"/>
|
||||||
<p2 x="1220" y="0"/>
|
<p2 x="1440" y="0"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="740" y="480"/>
|
<p1 x="740" y="480"/>
|
||||||
@ -813,10 +817,6 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="900" y="160"/>
|
<p1 x="900" y="160"/>
|
||||||
<p2 x="1080" y="160"/>
|
<p2 x="1080" y="160"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="340" y="160"/>
|
|
||||||
<p2 x="360" y="160"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1160" y="160"/>
|
<p1 x="1160" y="160"/>
|
||||||
<p2 x="1240" y="160"/>
|
<p2 x="1240" y="160"/>
|
||||||
@ -829,6 +829,10 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="540" y="160"/>
|
<p1 x="540" y="160"/>
|
||||||
<p2 x="660" y="160"/>
|
<p2 x="660" y="160"/>
|
||||||
</wire>
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="380" y="160"/>
|
||||||
|
<p2 x="400" y="160"/>
|
||||||
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="640" y="420"/>
|
<p1 x="640" y="420"/>
|
||||||
<p2 x="660" y="420"/>
|
<p2 x="660" y="420"/>
|
||||||
@ -854,7 +858,7 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="1240" y="360"/>
|
<p2 x="1240" y="360"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="320" y="360"/>
|
<p1 x="340" y="360"/>
|
||||||
<p2 x="360" y="360"/>
|
<p2 x="360" y="360"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
@ -882,16 +886,20 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="840" y="40"/>
|
<p2 x="840" y="40"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1240" y="40"/>
|
<p1 x="1200" y="40"/>
|
||||||
<p2 x="1260" y="40"/>
|
<p2 x="1220" y="40"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="880" y="460"/>
|
<p1 x="540" y="40"/>
|
||||||
<p2 x="900" y="460"/>
|
<p2 x="560" y="40"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="820" y="460"/>
|
<p1 x="380" y="140"/>
|
||||||
<p2 x="840" y="460"/>
|
<p2 x="400" y="140"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="500" y="140"/>
|
||||||
|
<p2 x="520" y="140"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="880" y="140"/>
|
<p1 x="880" y="140"/>
|
||||||
@ -901,30 +909,30 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="760" y="140"/>
|
<p1 x="760" y="140"/>
|
||||||
<p2 x="800" y="140"/>
|
<p2 x="800" y="140"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="340" y="140"/>
|
|
||||||
<p2 x="360" y="140"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="640" y="140"/>
|
<p1 x="640" y="140"/>
|
||||||
<p2 x="660" y="140"/>
|
<p2 x="660" y="140"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="460" y="140"/>
|
|
||||||
<p2 x="480" y="140"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1160" y="140"/>
|
<p1 x="1160" y="140"/>
|
||||||
<p2 x="1220" y="140"/>
|
<p2 x="1180" y="140"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1280" y="140"/>
|
<p1 x="1280" y="140"/>
|
||||||
<p2 x="1360" y="140"/>
|
<p2 x="1360" y="140"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1220" y="140"/>
|
<p1 x="1180" y="140"/>
|
||||||
<p2 x="1280" y="140"/>
|
<p2 x="1280" y="140"/>
|
||||||
</wire>
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="880" y="460"/>
|
||||||
|
<p2 x="900" y="460"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="820" y="460"/>
|
||||||
|
<p2 x="840" y="460"/>
|
||||||
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1000" y="300"/>
|
<p1 x="1000" y="300"/>
|
||||||
<p2 x="1060" y="300"/>
|
<p2 x="1060" y="300"/>
|
||||||
@ -933,6 +941,10 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="1140" y="300"/>
|
<p1 x="1140" y="300"/>
|
||||||
<p2 x="1160" y="300"/>
|
<p2 x="1160" y="300"/>
|
||||||
</wire>
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="340" y="240"/>
|
||||||
|
<p2 x="520" y="240"/>
|
||||||
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1340" y="400"/>
|
<p1 x="1340" y="400"/>
|
||||||
<p2 x="1360" y="400"/>
|
<p2 x="1360" y="400"/>
|
||||||
@ -954,12 +966,28 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="360" y="400"/>
|
<p2 x="360" y="400"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="340" y="80"/>
|
<p1 x="380" y="80"/>
|
||||||
<p2 x="1220" y="80"/>
|
<p2 x="1180" y="80"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="320" y="240"/>
|
<p1 x="380" y="180"/>
|
||||||
<p2 x="480" y="240"/>
|
<p2 x="400" y="180"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="1420" y="180"/>
|
||||||
|
<p2 x="1440" y="180"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="1160" y="180"/>
|
||||||
|
<p2 x="1220" y="180"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="1060" y="180"/>
|
||||||
|
<p2 x="1080" y="180"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="560" y="180"/>
|
||||||
|
<p2 x="660" y="180"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1340" y="340"/>
|
<p1 x="1340" y="340"/>
|
||||||
@ -978,24 +1006,20 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="840" y="500"/>
|
<p2 x="840" y="500"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1420" y="180"/>
|
<p1 x="500" y="120"/>
|
||||||
<p2 x="1440" y="180"/>
|
<p2 x="520" y="120"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="340" y="180"/>
|
<p1 x="380" y="120"/>
|
||||||
<p2 x="360" y="180"/>
|
<p2 x="400" y="120"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1160" y="180"/>
|
<p1 x="760" y="120"/>
|
||||||
<p2 x="1220" y="180"/>
|
<p2 x="840" y="120"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1060" y="180"/>
|
<p1 x="640" y="120"/>
|
||||||
<p2 x="1080" y="180"/>
|
<p2 x="660" y="120"/>
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="560" y="180"/>
|
|
||||||
<p2 x="660" y="180"/>
|
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="500" y="440"/>
|
<p1 x="500" y="440"/>
|
||||||
@ -1013,26 +1037,6 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="1000" y="280"/>
|
<p1 x="1000" y="280"/>
|
||||||
<p2 x="1020" y="280"/>
|
<p2 x="1020" y="280"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="540" y="120"/>
|
|
||||||
<p2 x="600" y="120"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="760" y="120"/>
|
|
||||||
<p2 x="840" y="120"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="460" y="120"/>
|
|
||||||
<p2 x="500" y="120"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="340" y="120"/>
|
|
||||||
<p2 x="360" y="120"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="600" y="120"/>
|
|
||||||
<p2 x="660" y="120"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1340" y="380"/>
|
<p1 x="1340" y="380"/>
|
||||||
<p2 x="1360" y="380"/>
|
<p2 x="1360" y="380"/>
|
||||||
@ -1066,8 +1070,8 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="1280" y="320"/>
|
<p2 x="1280" y="320"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="320" y="240"/>
|
<p1 x="640" y="0"/>
|
||||||
<p2 x="320" y="360"/>
|
<p2 x="640" y="120"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="580" y="380"/>
|
<p1 x="580" y="380"/>
|
||||||
@ -1081,25 +1085,21 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="900" y="160"/>
|
<p1 x="900" y="160"/>
|
||||||
<p2 x="900" y="460"/>
|
<p2 x="900" y="460"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="1220" y="60"/>
|
|
||||||
<p2 x="1220" y="80"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="1220" y="0"/>
|
|
||||||
<p2 x="1220" y="20"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1220" y="180"/>
|
<p1 x="1220" y="180"/>
|
||||||
<p2 x="1220" y="340"/>
|
<p2 x="1220" y="340"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="1220" y="80"/>
|
<p1 x="520" y="140"/>
|
||||||
<p2 x="1220" y="140"/>
|
<p2 x="520" y="240"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="520" y="140"/>
|
<p1 x="520" y="60"/>
|
||||||
<p2 x="520" y="160"/>
|
<p2 x="520" y="120"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="520" y="0"/>
|
||||||
|
<p2 x="520" y="20"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="520" y="600"/>
|
<p1 x="520" y="600"/>
|
||||||
@ -1118,21 +1118,13 @@ Single-Cycle CPU.</string>
|
|||||||
<p2 x="400" y="620"/>
|
<p2 x="400" y="620"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="340" y="180"/>
|
<p1 x="340" y="240"/>
|
||||||
<p2 x="340" y="320"/>
|
<p2 x="340" y="360"/>
|
||||||
</wire>
|
|
||||||
<wire>
|
|
||||||
<p1 x="340" y="80"/>
|
|
||||||
<p2 x="340" y="120"/>
|
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="340" y="600"/>
|
<p1 x="340" y="600"/>
|
||||||
<p2 x="340" y="620"/>
|
<p2 x="340" y="620"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="600" y="0"/>
|
|
||||||
<p2 x="600" y="120"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="600" y="600"/>
|
<p1 x="600" y="600"/>
|
||||||
<p2 x="600" y="620"/>
|
<p2 x="600" y="620"/>
|
||||||
@ -1141,6 +1133,18 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="1240" y="160"/>
|
<p1 x="1240" y="160"/>
|
||||||
<p2 x="1240" y="360"/>
|
<p2 x="1240" y="360"/>
|
||||||
</wire>
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="1180" y="60"/>
|
||||||
|
<p2 x="1180" y="80"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="1180" y="0"/>
|
||||||
|
<p2 x="1180" y="20"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="1180" y="80"/>
|
||||||
|
<p2 x="1180" y="140"/>
|
||||||
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="540" y="160"/>
|
<p1 x="540" y="160"/>
|
||||||
<p2 x="540" y="380"/>
|
<p2 x="540" y="380"/>
|
||||||
@ -1165,10 +1169,6 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="1440" y="180"/>
|
<p1 x="1440" y="180"/>
|
||||||
<p2 x="1440" y="360"/>
|
<p2 x="1440" y="360"/>
|
||||||
</wire>
|
</wire>
|
||||||
<wire>
|
|
||||||
<p1 x="480" y="140"/>
|
|
||||||
<p2 x="480" y="240"/>
|
|
||||||
</wire>
|
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="480" y="600"/>
|
<p1 x="480" y="600"/>
|
||||||
<p2 x="480" y="620"/>
|
<p2 x="480" y="620"/>
|
||||||
@ -1233,6 +1233,14 @@ Single-Cycle CPU.</string>
|
|||||||
<p1 x="440" y="600"/>
|
<p1 x="440" y="600"/>
|
||||||
<p2 x="440" y="620"/>
|
<p2 x="440" y="620"/>
|
||||||
</wire>
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="380" y="180"/>
|
||||||
|
<p2 x="380" y="320"/>
|
||||||
|
</wire>
|
||||||
|
<wire>
|
||||||
|
<p1 x="380" y="80"/>
|
||||||
|
<p2 x="380" y="120"/>
|
||||||
|
</wire>
|
||||||
<wire>
|
<wire>
|
||||||
<p1 x="380" y="600"/>
|
<p1 x="380" y="600"/>
|
||||||
<p2 x="380" y="620"/>
|
<p2 x="380" y="620"/>
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package de.neemann.digital.draw.library;
|
||||||
|
|
||||||
|
import de.neemann.digital.core.element.ElementTypeDescription;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for lazy loading of the circuits
|
||||||
|
* Created by hneemann on 25.03.17.
|
||||||
|
*/
|
||||||
|
public interface DescriptionCreator {
|
||||||
|
/**
|
||||||
|
* Is called if the description is needed in the circuit.
|
||||||
|
* Is not called to create the menus
|
||||||
|
*
|
||||||
|
* @return the description
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
ElementTypeDescription createDescription() throws IOException;
|
||||||
|
}
|
@ -3,7 +3,7 @@ package de.neemann.digital.draw.library;
|
|||||||
import de.neemann.digital.core.arithmetic.*;
|
import de.neemann.digital.core.arithmetic.*;
|
||||||
import de.neemann.digital.core.arithmetic.Comparator;
|
import de.neemann.digital.core.arithmetic.Comparator;
|
||||||
import de.neemann.digital.core.basic.*;
|
import de.neemann.digital.core.basic.*;
|
||||||
import de.neemann.digital.core.element.ElementTypeDescription;
|
import de.neemann.digital.core.element.*;
|
||||||
import de.neemann.digital.core.flipflops.FlipflopD;
|
import de.neemann.digital.core.flipflops.FlipflopD;
|
||||||
import de.neemann.digital.core.flipflops.FlipflopJK;
|
import de.neemann.digital.core.flipflops.FlipflopJK;
|
||||||
import de.neemann.digital.core.flipflops.FlipflopRS;
|
import de.neemann.digital.core.flipflops.FlipflopRS;
|
||||||
@ -19,13 +19,18 @@ import de.neemann.digital.core.switching.PFET;
|
|||||||
import de.neemann.digital.core.switching.Relay;
|
import de.neemann.digital.core.switching.Relay;
|
||||||
import de.neemann.digital.core.switching.Switch;
|
import de.neemann.digital.core.switching.Switch;
|
||||||
import de.neemann.digital.core.wiring.*;
|
import de.neemann.digital.core.wiring.*;
|
||||||
|
import de.neemann.digital.draw.elements.Circuit;
|
||||||
|
import de.neemann.digital.draw.elements.PinException;
|
||||||
import de.neemann.digital.draw.elements.Tunnel;
|
import de.neemann.digital.draw.elements.Tunnel;
|
||||||
|
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||||
import de.neemann.digital.gui.components.data.DummyElement;
|
import de.neemann.digital.gui.components.data.DummyElement;
|
||||||
import de.neemann.digital.gui.components.graphics.GraphicCard;
|
import de.neemann.digital.gui.components.graphics.GraphicCard;
|
||||||
import de.neemann.digital.gui.components.terminal.Keyboard;
|
import de.neemann.digital.gui.components.terminal.Keyboard;
|
||||||
import de.neemann.digital.gui.components.terminal.Terminal;
|
import de.neemann.digital.gui.components.terminal.Terminal;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.digital.testing.TestCaseElement;
|
import de.neemann.digital.testing.TestCaseElement;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -35,110 +40,146 @@ import java.util.*;
|
|||||||
* @author hneemann
|
* @author hneemann
|
||||||
*/
|
*/
|
||||||
public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer> {
|
public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer> {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(ElementLibrary.class);
|
||||||
|
|
||||||
private final HashMap<String, ElementTypeDescription> map = new HashMap<>();
|
private final HashMap<String, LibraryNode> map = new HashMap<>();
|
||||||
private ArrayList<ElementContainer> list = new ArrayList<>();
|
private final ArrayList<LibraryListener> listeners = new ArrayList<>();
|
||||||
private ElementNotFoundNotification elementNotFoundNotification;
|
private final LibraryNode root;
|
||||||
|
private ShapeFactory shapeFactory;
|
||||||
|
private LibraryNode customNode;
|
||||||
|
private File rootLibraryPath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance.
|
* Creates a new instance.
|
||||||
*/
|
*/
|
||||||
public ElementLibrary() {
|
public ElementLibrary() {
|
||||||
String menu = Lang.get("lib_Logic");
|
root = new LibraryNode("root");
|
||||||
add(And.DESCRIPTION, menu);
|
|
||||||
add(NAnd.DESCRIPTION, menu);
|
|
||||||
add(Or.DESCRIPTION, menu);
|
|
||||||
add(NOr.DESCRIPTION, menu);
|
|
||||||
add(XOr.DESCRIPTION, menu);
|
|
||||||
add(XNOr.DESCRIPTION, menu);
|
|
||||||
add(Not.DESCRIPTION, menu);
|
|
||||||
add(LookUpTable.DESCRIPTION, menu);
|
|
||||||
add(Delay.DESCRIPTION, menu);
|
|
||||||
|
|
||||||
menu = Lang.get("lib_io");
|
LibraryNode node = new LibraryNode(Lang.get("lib_Logic"));
|
||||||
add(Out.DESCRIPTION, menu);
|
node.add(And.DESCRIPTION);
|
||||||
add(Out.LEDDESCRIPTION, menu);
|
node.add(NAnd.DESCRIPTION);
|
||||||
add(In.DESCRIPTION, menu);
|
node.add(Or.DESCRIPTION);
|
||||||
add(Clock.DESCRIPTION, menu);
|
node.add(NOr.DESCRIPTION);
|
||||||
add(Button.DESCRIPTION, menu);
|
node.add(XOr.DESCRIPTION);
|
||||||
add(Probe.DESCRIPTION, menu);
|
node.add(XNOr.DESCRIPTION);
|
||||||
add(Out.SEVENDESCRIPTION, menu);
|
node.add(Not.DESCRIPTION);
|
||||||
add(Out.SEVENHEXDESCRIPTION, menu);
|
node.add(LookUpTable.DESCRIPTION);
|
||||||
add(DummyElement.DATADESCRIPTION, menu);
|
node.add(Delay.DESCRIPTION);
|
||||||
add(DummyElement.TEXTDESCRIPTION, menu);
|
root.add(node);
|
||||||
add(Keyboard.DESCRIPTION, menu);
|
|
||||||
add(Terminal.DESCRIPTION, menu);
|
|
||||||
|
|
||||||
menu = Lang.get("lib_wires");
|
node = new LibraryNode(Lang.get("lib_io"));
|
||||||
add(Const.DESCRIPTION, menu);
|
node.add(Out.DESCRIPTION);
|
||||||
add(Ground.DESCRIPTION, menu);
|
node.add(Out.LEDDESCRIPTION);
|
||||||
add(VDD.DESCRIPTION, menu);
|
node.add(In.DESCRIPTION);
|
||||||
add(Tunnel.DESCRIPTION, menu);
|
node.add(Clock.DESCRIPTION);
|
||||||
add(Splitter.DESCRIPTION, menu);
|
node.add(Button.DESCRIPTION);
|
||||||
add(PullUp.DESCRIPTION, menu);
|
node.add(Probe.DESCRIPTION);
|
||||||
add(PullDown.DESCRIPTION, menu);
|
node.add(Out.SEVENDESCRIPTION);
|
||||||
add(Driver.DESCRIPTION, menu);
|
node.add(Out.SEVENHEXDESCRIPTION);
|
||||||
add(DriverInvSel.DESCRIPTION, menu);
|
node.add(DummyElement.DATADESCRIPTION);
|
||||||
|
node.add(DummyElement.TEXTDESCRIPTION);
|
||||||
|
node.add(Keyboard.DESCRIPTION);
|
||||||
|
node.add(Terminal.DESCRIPTION);
|
||||||
|
root.add(node);
|
||||||
|
|
||||||
menu = Lang.get("lib_mux");
|
node = new LibraryNode(Lang.get("lib_wires"));
|
||||||
add(Multiplexer.DESCRIPTION, menu);
|
node.add(Const.DESCRIPTION);
|
||||||
add(Demultiplexer.DESCRIPTION, menu);
|
node.add(Ground.DESCRIPTION);
|
||||||
add(Decoder.DESCRIPTION, menu);
|
node.add(VDD.DESCRIPTION);
|
||||||
|
node.add(Tunnel.DESCRIPTION);
|
||||||
|
node.add(Splitter.DESCRIPTION);
|
||||||
|
node.add(PullUp.DESCRIPTION);
|
||||||
|
node.add(PullDown.DESCRIPTION);
|
||||||
|
node.add(Driver.DESCRIPTION);
|
||||||
|
node.add(DriverInvSel.DESCRIPTION);
|
||||||
|
root.add(node);
|
||||||
|
|
||||||
menu = Lang.get("lib_flipFlops");
|
node = new LibraryNode(Lang.get("lib_mux"));
|
||||||
add(FlipflopRS.DESCRIPTION, menu);
|
node.add(Multiplexer.DESCRIPTION);
|
||||||
add(FlipflopJK.DESCRIPTION, menu);
|
node.add(Demultiplexer.DESCRIPTION);
|
||||||
add(FlipflopD.DESCRIPTION, menu);
|
node.add(Decoder.DESCRIPTION);
|
||||||
add(FlipflopT.DESCRIPTION, menu);
|
root.add(node);
|
||||||
|
|
||||||
menu = Lang.get("lib_memory");
|
node = new LibraryNode(Lang.get("lib_flipFlops"));
|
||||||
add(Register.DESCRIPTION, menu);
|
node.add(FlipflopRS.DESCRIPTION);
|
||||||
add(ROM.DESCRIPTION, menu);
|
node.add(FlipflopJK.DESCRIPTION);
|
||||||
add(RAMDualPort.DESCRIPTION, menu);
|
node.add(FlipflopD.DESCRIPTION);
|
||||||
add(RAMSinglePort.DESCRIPTION, menu);
|
node.add(FlipflopT.DESCRIPTION);
|
||||||
add(RAMSinglePortSel.DESCRIPTION, menu);
|
root.add(node);
|
||||||
add(GraphicCard.DESCRIPTION, menu);
|
|
||||||
add(Counter.DESCRIPTION, menu);
|
|
||||||
|
|
||||||
menu = Lang.get("lib_arithmetic");
|
node = new LibraryNode(Lang.get("lib_memory"));
|
||||||
add(Add.DESCRIPTION, menu);
|
node.add(Register.DESCRIPTION);
|
||||||
add(Sub.DESCRIPTION, menu);
|
node.add(ROM.DESCRIPTION);
|
||||||
add(Mul.DESCRIPTION, menu);
|
node.add(RAMDualPort.DESCRIPTION);
|
||||||
add(Comparator.DESCRIPTION, menu);
|
node.add(RAMSinglePort.DESCRIPTION);
|
||||||
add(Neg.DESCRIPTION, menu);
|
node.add(RAMSinglePortSel.DESCRIPTION);
|
||||||
add(BitCount.DESCRIPTION, menu);
|
node.add(GraphicCard.DESCRIPTION);
|
||||||
|
node.add(Counter.DESCRIPTION);
|
||||||
|
root.add(node);
|
||||||
|
|
||||||
menu = Lang.get("lib_cplx");
|
node = new LibraryNode(Lang.get("lib_arithmetic"));
|
||||||
|
node.add(Add.DESCRIPTION);
|
||||||
|
node.add(Sub.DESCRIPTION);
|
||||||
|
node.add(Mul.DESCRIPTION);
|
||||||
|
node.add(Comparator.DESCRIPTION);
|
||||||
|
node.add(Neg.DESCRIPTION);
|
||||||
|
node.add(BitCount.DESCRIPTION);
|
||||||
|
root.add(node);
|
||||||
|
|
||||||
|
node = new LibraryNode(Lang.get("lib_cplx"));
|
||||||
// add(Diode.DESCRIPTION, menu); // see class DiodeTest for further information
|
// add(Diode.DESCRIPTION, menu); // see class DiodeTest for further information
|
||||||
add(DiodeForeward.DESCRIPTION, menu);
|
node.add(DiodeForeward.DESCRIPTION);
|
||||||
add(DiodeBackward.DESCRIPTION, menu);
|
node.add(DiodeBackward.DESCRIPTION);
|
||||||
add(Switch.DESCRIPTION, menu);
|
node.add(Switch.DESCRIPTION);
|
||||||
add(Relay.DESCRIPTION, menu);
|
node.add(Relay.DESCRIPTION);
|
||||||
add(NFET.DESCRIPTION, menu);
|
node.add(NFET.DESCRIPTION);
|
||||||
add(PFET.DESCRIPTION, menu);
|
node.add(PFET.DESCRIPTION);
|
||||||
add(Reset.DESCRIPTION, menu);
|
node.add(Reset.DESCRIPTION);
|
||||||
add(Break.DESCRIPTION, menu);
|
node.add(Break.DESCRIPTION);
|
||||||
|
root.add(node);
|
||||||
|
|
||||||
menu = Lang.get("lib_test");
|
node = new LibraryNode(Lang.get("lib_test"));
|
||||||
add(TestCaseElement.TESTCASEDESCRIPTION, menu);
|
node.add(TestCaseElement.TESTCASEDESCRIPTION);
|
||||||
}
|
root.add(node);
|
||||||
|
|
||||||
private void add(ElementTypeDescription description, String treePath) {
|
populateNodeMap();
|
||||||
String name = description.getName();
|
|
||||||
map.put(name, description);
|
|
||||||
list.add(new ElementContainer(description, treePath));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a description to the library
|
* Sets the shape factory used to import sub circuits
|
||||||
*
|
*
|
||||||
* @param description the description
|
* @param shapeFactory the shape factory
|
||||||
* @param file the file which was loaded
|
|
||||||
*/
|
*/
|
||||||
public void addDescription(ElementTypeDescription description, File file) {
|
public void setShapeFactory(ShapeFactory shapeFactory) {
|
||||||
map.put(file.getName(), description);
|
this.shapeFactory = shapeFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void populateNodeMap() {
|
||||||
|
map.clear();
|
||||||
|
root.traverse(libraryNode -> {
|
||||||
|
if (libraryNode.isLeaf()) {
|
||||||
|
map.put(libraryNode.getName(), libraryNode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the root library path
|
||||||
|
*
|
||||||
|
* @param rootLibraryPath the path
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public void setFilePath(File rootLibraryPath) throws IOException {
|
||||||
|
if (rootLibraryPath == null) {
|
||||||
|
if (this.rootLibraryPath != null) {
|
||||||
|
this.rootLibraryPath = null;
|
||||||
|
rescanFolder();
|
||||||
|
}
|
||||||
|
} else if (!rootLibraryPath.equals(this.rootLibraryPath)) {
|
||||||
|
this.rootLibraryPath = rootLibraryPath;
|
||||||
|
rescanFolder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a {@link ElementTypeDescription} by a given name.
|
* Returns a {@link ElementTypeDescription} by a given name.
|
||||||
@ -149,60 +190,123 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
|||||||
* @throws ElementNotFoundException ElementNotFoundException
|
* @throws ElementNotFoundException ElementNotFoundException
|
||||||
*/
|
*/
|
||||||
public ElementTypeDescription getElementType(String elementName) throws ElementNotFoundException {
|
public ElementTypeDescription getElementType(String elementName) throws ElementNotFoundException {
|
||||||
ElementTypeDescription description = map.get(elementName);
|
try {
|
||||||
if (description != null)
|
LibraryNode description = map.get(elementName);
|
||||||
return description;
|
if (description != null)
|
||||||
|
return description.getDescription();
|
||||||
|
|
||||||
elementName = elementName.replace("\\", "/"); // effects only some old files!
|
// effects only some old files!
|
||||||
|
elementName = elementName.replace("\\", "/");
|
||||||
File file = new File(elementName);
|
if (elementName.contains("/")) {
|
||||||
|
elementName = new File(elementName).getName();
|
||||||
description = map.get(file.getName());
|
|
||||||
if (description != null)
|
|
||||||
return description;
|
|
||||||
|
|
||||||
if (elementNotFoundNotification != null)
|
|
||||||
try {
|
|
||||||
description = elementNotFoundNotification.elementNotFound(file);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new ElementNotFoundException(Lang.get("msg_errorImportingModel", elementName), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (description != null)
|
description = map.get(elementName);
|
||||||
return description;
|
if (description != null)
|
||||||
|
return description.getDescription();
|
||||||
|
|
||||||
|
if (rootLibraryPath == null)
|
||||||
|
throw new RuntimeException("no root path set");
|
||||||
|
|
||||||
|
rescanFolder();
|
||||||
|
|
||||||
|
description = map.get(elementName);
|
||||||
|
if (description != null)
|
||||||
|
return description.getDescription();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ElementNotFoundException(Lang.get("msg_errorImportingModel"), e);
|
||||||
|
}
|
||||||
|
|
||||||
throw new ElementNotFoundException(Lang.get("err_element_N_notFound", elementName));
|
throw new ElementNotFoundException(Lang.get("err_element_N_notFound", elementName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void rescanFolder() {
|
||||||
public Iterator<ElementContainer> iterator() {
|
LOGGER.debug("rescan folder");
|
||||||
HashSet<String> baseElements = new HashSet<>();
|
if (customNode == null) {
|
||||||
for (ElementContainer ec : list) {
|
customNode = new LibraryNode(Lang.get("menu_custom"));
|
||||||
baseElements.add(ec.getDescription().getName());
|
root.add(customNode);
|
||||||
}
|
} else customNode.removeAll();
|
||||||
ArrayList<ElementContainer> custom = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, ElementTypeDescription> entry : map.entrySet()) {
|
|
||||||
if (!baseElements.contains(entry.getValue().getName())) {
|
|
||||||
custom.add(new ElementContainer(entry.getValue(), Lang.get("menu_custom")));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (custom.isEmpty())
|
if (rootLibraryPath != null)
|
||||||
return list.iterator();
|
scanFolder(rootLibraryPath, customNode);
|
||||||
else {
|
|
||||||
Collections.sort(custom, (c1, c2) -> c1.getDescription().getTranslatedName().compareToIgnoreCase(c2.getDescription().getTranslatedName()));
|
populateNodeMap();
|
||||||
custom.addAll(list);
|
|
||||||
return custom.iterator();
|
fireLibraryChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fireLibraryChanged() {
|
||||||
|
for (LibraryListener l : listeners)
|
||||||
|
l.libraryChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scanFolder(File path, LibraryNode node) {
|
||||||
|
File[] list = path.listFiles();
|
||||||
|
if (list != null) {
|
||||||
|
ArrayList<File> orderedList = new ArrayList<>(Arrays.asList(list));
|
||||||
|
orderedList.sort((f1, f2) -> f1.getName().compareToIgnoreCase(f2.getName()));
|
||||||
|
for (File f : orderedList) {
|
||||||
|
if (f.isDirectory()) {
|
||||||
|
LibraryNode n = new LibraryNode(f.getName());
|
||||||
|
scanFolder(f, n);
|
||||||
|
if (!n.isEmpty())
|
||||||
|
node.add(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (File f : orderedList) {
|
||||||
|
final String name = f.getName();
|
||||||
|
if (f.isFile() && name.endsWith(".dig"))
|
||||||
|
node.add(importElement(f));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setes the {@link ElementNotFoundNotification} which can be calle if a element is not present.
|
* Adds a listener to this library
|
||||||
*
|
*
|
||||||
* @param elementNotFoundNotification elementNotFoundNotification
|
* @param listener the listener to add
|
||||||
*/
|
*/
|
||||||
public void setElementNotFoundNotification(ElementNotFoundNotification elementNotFoundNotification) {
|
public void addListener(LibraryListener listener) {
|
||||||
this.elementNotFoundNotification = elementNotFoundNotification;
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a listener from this library
|
||||||
|
*
|
||||||
|
* @param listener the listener to remove
|
||||||
|
*/
|
||||||
|
public void removeListener(LibraryListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<ElementContainer> iterator() {
|
||||||
|
ArrayList<ElementContainer> nodes = new ArrayList<>();
|
||||||
|
for (LibraryNode n : getRoot())
|
||||||
|
addToList(nodes, n, "");
|
||||||
|
return nodes.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToList(ArrayList<ElementContainer> nodes, LibraryNode node, String path) {
|
||||||
|
if (node.isLeaf()) {
|
||||||
|
if (node.isDescriptionLoaded()) {
|
||||||
|
try {
|
||||||
|
nodes.add(new ElementContainer(node.getDescription(), path));
|
||||||
|
} catch (IOException e) {
|
||||||
|
// can not happen because description is present!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
for (LibraryNode n : node)
|
||||||
|
addToList(nodes, n, concat(path, node.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String concat(String path, String name) {
|
||||||
|
if (path.length() == 0)
|
||||||
|
return name;
|
||||||
|
return path + " - " + name;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,6 +318,120 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
|||||||
map.remove(name.getName());
|
map.remove(name.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates all entries
|
||||||
|
*
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public void updateEntries() throws IOException {
|
||||||
|
rescanFolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the root element
|
||||||
|
*/
|
||||||
|
public LibraryNode getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LibraryNode importElement(File file) {
|
||||||
|
return new LibraryNode(file.getName(), () -> {
|
||||||
|
try {
|
||||||
|
LOGGER.debug("load element " + file);
|
||||||
|
Circuit circuit = Circuit.loadCircuit(file, shapeFactory);
|
||||||
|
ElementTypeDescriptionCustom description =
|
||||||
|
new ElementTypeDescriptionCustom(file,
|
||||||
|
attributes -> new CustomElement(circuit, ElementLibrary.this, file),
|
||||||
|
circuit.getAttributes(), circuit.getInputNames());
|
||||||
|
description.setShortName(createShortName(file));
|
||||||
|
|
||||||
|
String descriptionText = circuit.getAttributes().get(Keys.DESCRIPTION);
|
||||||
|
if (descriptionText != null && descriptionText.length() > 0) {
|
||||||
|
description.setDescription(descriptionText);
|
||||||
|
}
|
||||||
|
return description;
|
||||||
|
} catch (PinException e) {
|
||||||
|
throw new IOException(Lang.get("msg_errorImportingModel"), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createShortName(File file) {
|
||||||
|
return createShortName(file.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createShortName(String name) {
|
||||||
|
if (name.endsWith(".dig")) return name.substring(0, name.length() - 4);
|
||||||
|
|
||||||
|
String transName = Lang.getNull("elem_" + name);
|
||||||
|
if (transName == null)
|
||||||
|
return name;
|
||||||
|
else
|
||||||
|
return transName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The description of a nested element.
|
||||||
|
* This is a complete circuit which is used as a element.
|
||||||
|
*/
|
||||||
|
public static class ElementTypeDescriptionCustom extends ElementTypeDescription {
|
||||||
|
private final File file;
|
||||||
|
private final ElementAttributes attributes;
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new element
|
||||||
|
*
|
||||||
|
* @param file the file which is loaded
|
||||||
|
* @param elementFactory a element factory which is used to create concrete elements if needed
|
||||||
|
* @param attributes the attributes of the element
|
||||||
|
* @param inputNames the names of the input signals
|
||||||
|
*/
|
||||||
|
public ElementTypeDescriptionCustom(File file, ElementFactory elementFactory, ElementAttributes attributes, PinDescription... inputNames) {
|
||||||
|
super(file.getName(), elementFactory, inputNames);
|
||||||
|
this.file = file;
|
||||||
|
this.attributes = attributes;
|
||||||
|
setShortName(file.getName());
|
||||||
|
addAttribute(Keys.ROTATE);
|
||||||
|
addAttribute(Keys.LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the filename
|
||||||
|
* the retuned file is opened if the user wants to modify the element
|
||||||
|
*
|
||||||
|
* @return the filename
|
||||||
|
*/
|
||||||
|
public File getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the elements attributes
|
||||||
|
*/
|
||||||
|
public ElementAttributes getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a custom description for this field
|
||||||
|
*
|
||||||
|
* @param description the description
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription(ElementAttributes elementAttributes) {
|
||||||
|
if (description != null)
|
||||||
|
return description;
|
||||||
|
else
|
||||||
|
return super.getDescription(elementAttributes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to store a elements name and its position in the elements menu.
|
* Used to store a elements name and its position in the elements menu.
|
||||||
*/
|
*/
|
||||||
@ -227,7 +445,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
|
|||||||
* @param typeDescription the elements typeDescription
|
* @param typeDescription the elements typeDescription
|
||||||
* @param treePath the elements menu path
|
* @param treePath the elements menu path
|
||||||
*/
|
*/
|
||||||
public ElementContainer(ElementTypeDescription typeDescription, String treePath) {
|
ElementContainer(ElementTypeDescription typeDescription, String treePath) {
|
||||||
this.name = typeDescription;
|
this.name = typeDescription;
|
||||||
this.treePath = treePath;
|
this.treePath = treePath;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package de.neemann.digital.draw.library;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener to notify library uses if the library changes
|
||||||
|
* Created by hneemann on 25.03.17.
|
||||||
|
*/
|
||||||
|
public interface LibraryListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* called if library changes
|
||||||
|
*/
|
||||||
|
void libraryChanged();
|
||||||
|
}
|
159
src/main/java/de/neemann/digital/draw/library/LibraryNode.java
Normal file
159
src/main/java/de/neemann/digital/draw/library/LibraryNode.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package de.neemann.digital.draw.library;
|
||||||
|
|
||||||
|
import de.neemann.digital.core.element.ElementTypeDescription;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node in the components library
|
||||||
|
* Created by hneemann on 25.03.17.
|
||||||
|
*/
|
||||||
|
public class LibraryNode implements Iterable<LibraryNode> {
|
||||||
|
|
||||||
|
private final ArrayList<LibraryNode> children;
|
||||||
|
private final String translatedName;
|
||||||
|
private final String name;
|
||||||
|
private final DescriptionCreator creator;
|
||||||
|
private ElementTypeDescription description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new node with the given name.
|
||||||
|
* The node can have children
|
||||||
|
*
|
||||||
|
* @param name name of the node
|
||||||
|
*/
|
||||||
|
LibraryNode(String name) {
|
||||||
|
this.name = name;
|
||||||
|
this.translatedName = name;
|
||||||
|
this.children = new ArrayList<>();
|
||||||
|
this.description = null;
|
||||||
|
this.creator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new leaf
|
||||||
|
*
|
||||||
|
* @param description the description
|
||||||
|
*/
|
||||||
|
private LibraryNode(ElementTypeDescription description) {
|
||||||
|
this.children = null;
|
||||||
|
this.description = description;
|
||||||
|
this.name = description.getName();
|
||||||
|
this.translatedName = description.getTranslatedName();
|
||||||
|
this.creator = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new leaf
|
||||||
|
*
|
||||||
|
* @param name the name of the leaf
|
||||||
|
* @param creator used to create the {@link ElementTypeDescription} if necessary
|
||||||
|
*/
|
||||||
|
LibraryNode(String name, DescriptionCreator creator) {
|
||||||
|
this.children = null;
|
||||||
|
this.name = name;
|
||||||
|
this.translatedName = name;
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a node.
|
||||||
|
* Throws an exception if this node is a leaf
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
*/
|
||||||
|
void add(LibraryNode node) {
|
||||||
|
children.add(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(ElementTypeDescription node) {
|
||||||
|
add(new LibraryNode(node));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Traverse the tree
|
||||||
|
*
|
||||||
|
* @param v a visitor
|
||||||
|
* @param <V> the type of the visitor
|
||||||
|
* @return the visitor
|
||||||
|
*/
|
||||||
|
public <V extends Visitor> V traverse(V v) {
|
||||||
|
v.visit(this);
|
||||||
|
if (children != null) {
|
||||||
|
for (LibraryNode tn : children)
|
||||||
|
tn.traverse(v);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return trie if this is a leaf
|
||||||
|
*/
|
||||||
|
public boolean isLeaf() {
|
||||||
|
return description != null || creator != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the description is already loaded
|
||||||
|
*/
|
||||||
|
public boolean isDescriptionLoaded() {
|
||||||
|
return description != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the description of the element
|
||||||
|
*
|
||||||
|
* @return the description
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
public ElementTypeDescription getDescription() throws IOException {
|
||||||
|
if (description == null)
|
||||||
|
description = creator.createDescription();
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the translated name of the element
|
||||||
|
*/
|
||||||
|
public String getTranslatedName() {
|
||||||
|
return translatedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name od id of this element
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<LibraryNode> iterator() {
|
||||||
|
return children.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* all children are removed
|
||||||
|
*/
|
||||||
|
public void removeAll() {
|
||||||
|
children.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this node is empty
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
if (isLeaf())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return children.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return returns the description if present, null otherwise
|
||||||
|
*/
|
||||||
|
public ElementTypeDescription getDescriptionOrNull() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
15
src/main/java/de/neemann/digital/draw/library/Visitor.java
Normal file
15
src/main/java/de/neemann/digital/draw/library/Visitor.java
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package de.neemann.digital.draw.library;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visits all elements of the elements tree
|
||||||
|
* Created by hneemann on 25.03.17.
|
||||||
|
*/
|
||||||
|
public interface Visitor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called on every node
|
||||||
|
*
|
||||||
|
* @param libraryNode the node
|
||||||
|
*/
|
||||||
|
void visit(LibraryNode libraryNode);
|
||||||
|
}
|
@ -23,7 +23,6 @@ import de.neemann.digital.draw.shapes.ieee.IEEEAndShape;
|
|||||||
import de.neemann.digital.draw.shapes.ieee.IEEENotShape;
|
import de.neemann.digital.draw.shapes.ieee.IEEENotShape;
|
||||||
import de.neemann.digital.draw.shapes.ieee.IEEEOrShape;
|
import de.neemann.digital.draw.shapes.ieee.IEEEOrShape;
|
||||||
import de.neemann.digital.draw.shapes.ieee.IEEEXOrShape;
|
import de.neemann.digital.draw.shapes.ieee.IEEEXOrShape;
|
||||||
import de.neemann.digital.gui.LibrarySelector;
|
|
||||||
import de.neemann.digital.gui.components.data.DummyElement;
|
import de.neemann.digital.gui.components.data.DummyElement;
|
||||||
import de.neemann.digital.lang.Lang;
|
import de.neemann.digital.lang.Lang;
|
||||||
import de.neemann.digital.testing.TestCaseElement;
|
import de.neemann.digital.testing.TestCaseElement;
|
||||||
@ -57,6 +56,7 @@ public final class ShapeFactory {
|
|||||||
*/
|
*/
|
||||||
public ShapeFactory(ElementLibrary library, boolean ieee) {
|
public ShapeFactory(ElementLibrary library, boolean ieee) {
|
||||||
this.library = library;
|
this.library = library;
|
||||||
|
library.setShapeFactory(this);
|
||||||
if (ieee) {
|
if (ieee) {
|
||||||
map.put(And.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, false));
|
map.put(And.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, false));
|
||||||
map.put(NAnd.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, true));
|
map.put(NAnd.DESCRIPTION.getName(), (attributes, inputs, outputs) -> new IEEEAndShape(inputs, outputs, true));
|
||||||
@ -136,8 +136,8 @@ public final class ShapeFactory {
|
|||||||
throw new NodeException(Lang.get("err_noShapeFoundFor_N", elementName));
|
throw new NodeException(Lang.get("err_noShapeFoundFor_N", elementName));
|
||||||
else {
|
else {
|
||||||
ElementTypeDescription pt = library.getElementType(elementName);
|
ElementTypeDescription pt = library.getElementType(elementName);
|
||||||
if (pt instanceof LibrarySelector.ElementTypeDescriptionCustom) {
|
if (pt instanceof ElementLibrary.ElementTypeDescriptionCustom) {
|
||||||
LibrarySelector.ElementTypeDescriptionCustom customDescr = (LibrarySelector.ElementTypeDescriptionCustom) pt;
|
ElementLibrary.ElementTypeDescriptionCustom customDescr = (ElementLibrary.ElementTypeDescriptionCustom) pt;
|
||||||
return new GenericShape(
|
return new GenericShape(
|
||||||
pt.getShortName(),
|
pt.getShortName(),
|
||||||
pt.getInputDescription(elementAttributes),
|
pt.getInputDescription(elementAttributes),
|
||||||
|
@ -3,6 +3,7 @@ package de.neemann.digital.gui;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The InsertHistory puts the most frequently used elements to the toolbar of the main window.
|
* The InsertHistory puts the most frequently used elements to the toolbar of the main window.
|
||||||
@ -41,15 +42,20 @@ public class InsertHistory {
|
|||||||
bar.add(wrapper);
|
bar.add(wrapper);
|
||||||
if (wrappers.size() > MAX_ICONS) {
|
if (wrappers.size() > MAX_ICONS) {
|
||||||
int oldest = findOldestIndex();
|
int oldest = findOldestIndex();
|
||||||
wrapper = wrappers.get(oldest);
|
removeWrapperFromBar(wrappers.get(oldest));
|
||||||
bar.remove(wrapper.componentPosition);
|
|
||||||
for (int i = oldest; i < wrappers.size(); i++)
|
|
||||||
wrappers.get(i).componentPosition--;
|
|
||||||
wrappers.remove(oldest);
|
wrappers.remove(oldest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeWrapperFromBar(WrapperAction wrapper) {
|
||||||
|
final int position = wrapper.componentPosition;
|
||||||
|
bar.remove(position);
|
||||||
|
for (WrapperAction w : wrappers)
|
||||||
|
if (w.componentPosition > position)
|
||||||
|
w.componentPosition--;
|
||||||
|
}
|
||||||
|
|
||||||
private int findOldestIndex() {
|
private int findOldestIndex() {
|
||||||
int found = -1;
|
int found = -1;
|
||||||
int oldestTime = mainTime;
|
int oldestTime = mainTime;
|
||||||
@ -70,8 +76,24 @@ public class InsertHistory {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class WrapperAction extends AbstractAction {
|
/**
|
||||||
|
* remove custom components
|
||||||
|
*/
|
||||||
|
public void removeCustom() {
|
||||||
|
Iterator<WrapperAction> it = wrappers.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
WrapperAction w = it.next();
|
||||||
|
if (w.action instanceof LibrarySelector.InsertAction) {
|
||||||
|
if (((LibrarySelector.InsertAction) w.action).isCustom()) {
|
||||||
|
removeWrapperFromBar(w);
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bar.revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class WrapperAction extends AbstractAction {
|
||||||
private final AbstractAction action;
|
private final AbstractAction action;
|
||||||
private int componentPosition;
|
private int componentPosition;
|
||||||
private int time;
|
private int time;
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
package de.neemann.digital.gui;
|
package de.neemann.digital.gui;
|
||||||
|
|
||||||
import de.neemann.digital.core.element.*;
|
|
||||||
import de.neemann.digital.draw.elements.Circuit;
|
|
||||||
import de.neemann.digital.draw.elements.PinException;
|
|
||||||
import de.neemann.digital.draw.elements.VisualElement;
|
import de.neemann.digital.draw.elements.VisualElement;
|
||||||
import de.neemann.digital.draw.graphics.Vector;
|
import de.neemann.digital.draw.graphics.Vector;
|
||||||
import de.neemann.digital.draw.library.CustomElement;
|
|
||||||
import de.neemann.digital.draw.library.ElementLibrary;
|
import de.neemann.digital.draw.library.ElementLibrary;
|
||||||
import de.neemann.digital.draw.library.ElementNotFoundNotification;
|
import de.neemann.digital.draw.library.LibraryListener;
|
||||||
|
import de.neemann.digital.draw.library.LibraryNode;
|
||||||
import de.neemann.digital.draw.shapes.ShapeFactory;
|
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||||
import de.neemann.digital.gui.components.CircuitComponent;
|
import de.neemann.digital.gui.components.CircuitComponent;
|
||||||
import de.neemann.digital.gui.state.State;
|
import de.neemann.digital.gui.state.State;
|
||||||
@ -15,16 +12,10 @@ import de.neemann.digital.lang.Lang;
|
|||||||
import de.neemann.gui.ErrorMessage;
|
import de.neemann.gui.ErrorMessage;
|
||||||
import de.neemann.gui.StringUtils;
|
import de.neemann.gui.StringUtils;
|
||||||
import de.neemann.gui.ToolTipAction;
|
import de.neemann.gui.ToolTipAction;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The LibrarySelector is responsible for building the menu used to select items for adding them to the circuit.
|
* The LibrarySelector is responsible for building the menu used to select items for adding them to the circuit.
|
||||||
@ -32,22 +23,17 @@ import java.util.HashMap;
|
|||||||
*
|
*
|
||||||
* @author hneemann
|
* @author hneemann
|
||||||
*/
|
*/
|
||||||
public class LibrarySelector implements ElementNotFoundNotification {
|
public class LibrarySelector implements LibraryListener {
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(LibrarySelector.class);
|
|
||||||
|
|
||||||
private final ElementLibrary library;
|
private final ElementLibrary library;
|
||||||
private final ShapeFactory shapeFactory;
|
private final ShapeFactory shapeFactory;
|
||||||
private final State elementState;
|
private final State elementState;
|
||||||
private File filePath;
|
private JMenu componentsMenu;
|
||||||
private JMenu customMenu;
|
|
||||||
private InsertHistory insertHistory;
|
private InsertHistory insertHistory;
|
||||||
private CircuitComponent circuitComponent;
|
private CircuitComponent circuitComponent;
|
||||||
private ArrayList<ImportedItem> importedElements;
|
|
||||||
private HashMap<String, File> treeFileMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new library selector.
|
* Creates a new library selector.
|
||||||
* the elementState is used to seht the window to the elemetEdit mode if a new element is added to the circuit.
|
* the elementState is used to set the window to the elementEdit mode if a new element is added to the circuit.
|
||||||
*
|
*
|
||||||
* @param library the library to select elements from
|
* @param library the library to select elements from
|
||||||
* @param shapeFactory The shape factory
|
* @param shapeFactory The shape factory
|
||||||
@ -55,10 +41,9 @@ public class LibrarySelector implements ElementNotFoundNotification {
|
|||||||
*/
|
*/
|
||||||
public LibrarySelector(ElementLibrary library, ShapeFactory shapeFactory, State elementState) {
|
public LibrarySelector(ElementLibrary library, ShapeFactory shapeFactory, State elementState) {
|
||||||
this.library = library;
|
this.library = library;
|
||||||
|
library.addListener(this);
|
||||||
this.shapeFactory = shapeFactory;
|
this.shapeFactory = shapeFactory;
|
||||||
this.elementState = elementState;
|
this.elementState = elementState;
|
||||||
library.setElementNotFoundNotification(this);
|
|
||||||
importedElements = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,64 +58,47 @@ public class LibrarySelector implements ElementNotFoundNotification {
|
|||||||
public JMenu buildMenu(InsertHistory insertHistory, CircuitComponent circuitComponent) {
|
public JMenu buildMenu(InsertHistory insertHistory, CircuitComponent circuitComponent) {
|
||||||
this.insertHistory = insertHistory;
|
this.insertHistory = insertHistory;
|
||||||
this.circuitComponent = circuitComponent;
|
this.circuitComponent = circuitComponent;
|
||||||
JMenu parts = new JMenu(Lang.get("menu_elements"));
|
componentsMenu = new JMenu(Lang.get("menu_elements"));
|
||||||
|
libraryChanged();
|
||||||
|
|
||||||
customMenu = new JMenu(Lang.get("menu_custom"));
|
return componentsMenu;
|
||||||
parts.add(customMenu);
|
|
||||||
|
|
||||||
customMenu.add(new ToolTipAction(Lang.get("menu_import")) {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
JFileChooser fc = new JFileChooser(filePath);
|
|
||||||
fc.setFileFilter(new FileNameExtensionFilter("Circuit", "dig"));
|
|
||||||
if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
|
|
||||||
try {
|
|
||||||
Imported imp = importElement(fc.getSelectedFile());
|
|
||||||
if (imp != null) {
|
|
||||||
VisualElement visualElement = new VisualElement(imp.description.getName()).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory);
|
|
||||||
elementState.enter();
|
|
||||||
circuitComponent.setPartToInsert(visualElement);
|
|
||||||
insertHistory.add(imp.insertAction);
|
|
||||||
}
|
|
||||||
} catch (IOException e1) {
|
|
||||||
new ErrorMessage(Lang.get("msg_errorImportingModel")).addCause(e1).show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.setToolTip(Lang.get("menu_import_tt")).createJMenuItem());
|
|
||||||
|
|
||||||
customMenu.add(new ToolTipAction(Lang.get("menu_refresh")) {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
removeCustomElements();
|
|
||||||
}
|
|
||||||
}.setToolTip(Lang.get("menu_refresh_tt")).createJMenuItem());
|
|
||||||
|
|
||||||
|
|
||||||
JMenu subMenu = null;
|
|
||||||
String lastPath = null;
|
|
||||||
for (ElementLibrary.ElementContainer elementContainer : library) {
|
|
||||||
String path = elementContainer.getTreePath();
|
|
||||||
if (!path.equals(lastPath)) {
|
|
||||||
subMenu = new JMenu(path);
|
|
||||||
parts.add(subMenu);
|
|
||||||
lastPath = path;
|
|
||||||
}
|
|
||||||
subMenu.add(new InsertAction(elementContainer.getDescription(), insertHistory, circuitComponent)
|
|
||||||
.setToolTip(createToolTipText(elementContainer.getDescription().getName()))
|
|
||||||
.createJMenuItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
return parts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* removes all custom elements
|
public void libraryChanged() {
|
||||||
*/
|
componentsMenu.removeAll();
|
||||||
public void removeCustomElements() {
|
|
||||||
for (ImportedItem item : importedElements) {
|
for (LibraryNode n : library.getRoot())
|
||||||
library.removeElement(item.file);
|
addComponents(componentsMenu, n);
|
||||||
customMenu.remove(item.menuEntry);
|
|
||||||
|
insertHistory.removeCustom();
|
||||||
|
|
||||||
|
JMenuItem m = componentsMenu.getItem(componentsMenu.getItemCount() - 1);
|
||||||
|
if (m instanceof JMenu) {
|
||||||
|
((JMenu) m).add(new ToolTipAction(Lang.get("menu_import")) {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
try {
|
||||||
|
library.updateEntries();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorImportingModel")).addCause(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.setToolTip(Lang.get("menu_import_tt")).createJMenuItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addComponents(JMenu parts, LibraryNode node) {
|
||||||
|
if (node.isLeaf()) {
|
||||||
|
parts.add(new InsertAction(node, insertHistory, circuitComponent)
|
||||||
|
.setToolTip(createToolTipText(node.getName()))
|
||||||
|
.createJMenuItem());
|
||||||
|
} else {
|
||||||
|
JMenu subMenu = new JMenu(node.getName());
|
||||||
|
for (LibraryNode child : node)
|
||||||
|
addComponents(subMenu, child);
|
||||||
|
parts.add(subMenu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,232 +106,50 @@ public class LibrarySelector implements ElementNotFoundNotification {
|
|||||||
return StringUtils.textToHTML(Lang.getNull("elem_" + elementName + "_tt"));
|
return StringUtils.textToHTML(Lang.getNull("elem_" + elementName + "_tt"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
final class InsertAction extends ToolTipAction {
|
||||||
* sets the file path which is used to load missing nested elements
|
private final LibraryNode node;
|
||||||
*
|
|
||||||
* @param filePath the file path
|
|
||||||
*/
|
|
||||||
public void setFilePath(File filePath) {
|
|
||||||
treeFileMap = null;
|
|
||||||
this.filePath = filePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ElementTypeDescription elementNotFound(File file) throws IOException {
|
|
||||||
// check if there is a file with the given name in the current directory
|
|
||||||
// if so, load this file!
|
|
||||||
File primary = new File(filePath, file.getName());
|
|
||||||
if (primary.exists())
|
|
||||||
file = primary;
|
|
||||||
|
|
||||||
// check if there is a file with the given name below the current directory
|
|
||||||
// if so, load this file!
|
|
||||||
File f = getFileFromTree(file.getName());
|
|
||||||
if (f != null)
|
|
||||||
return importElement(f).description;
|
|
||||||
|
|
||||||
// than check if the exact given file exists
|
|
||||||
if (file.exists())
|
|
||||||
return importElement(file).description;
|
|
||||||
|
|
||||||
// could not find the given file
|
|
||||||
throw new IOException(Lang.get("err_couldNotFindIncludedFile_N0", file));
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getFileFromTree(String name) throws IOException {
|
|
||||||
if (treeFileMap == null) {
|
|
||||||
treeFileMap = new HashMap<>();
|
|
||||||
populateTreeFileMap(treeFileMap, filePath);
|
|
||||||
} else {
|
|
||||||
if (!treeFileMap.containsKey(name)) { // if file not in map rescan folder
|
|
||||||
treeFileMap.clear();
|
|
||||||
populateTreeFileMap(treeFileMap, filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return treeFileMap.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void populateTreeFileMap(HashMap<String, File> map, File path) throws IOException {
|
|
||||||
File[] list = path.listFiles();
|
|
||||||
if (list != null) {
|
|
||||||
for (File f : list) {
|
|
||||||
final String name = f.getName();
|
|
||||||
if (f.isFile() && name.endsWith(".dig")) {
|
|
||||||
if (map.containsKey(name))
|
|
||||||
throw new IOException(Lang.get("err_file_N0_ExistsTwiceBelow_N1", name, filePath));
|
|
||||||
map.put(name, f);
|
|
||||||
}
|
|
||||||
if (f.isDirectory())
|
|
||||||
populateTreeFileMap(map, f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String getActionName(ElementTypeDescription typeDescription) {
|
|
||||||
if (typeDescription instanceof ElementTypeDescriptionCustom)
|
|
||||||
return typeDescription.getShortName();
|
|
||||||
else
|
|
||||||
return typeDescription.getTranslatedName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class InsertAction extends ToolTipAction {
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final InsertHistory insertHistory;
|
private final InsertHistory insertHistory;
|
||||||
private final CircuitComponent circuitComponent;
|
private final CircuitComponent circuitComponent;
|
||||||
|
|
||||||
private InsertAction(ElementTypeDescription typeDescription, InsertHistory insertHistory, CircuitComponent circuitComponent) {
|
private InsertAction(LibraryNode node, InsertHistory insertHistory, CircuitComponent circuitComponent) {
|
||||||
super(getActionName(typeDescription), new VisualElement(typeDescription.getName()).setShapeFactory(shapeFactory).createIcon(75));
|
super(node.getTranslatedName(), createIcon(node, shapeFactory));
|
||||||
this.name = typeDescription.getName();
|
this.node = node;
|
||||||
this.insertHistory = insertHistory;
|
this.insertHistory = insertHistory;
|
||||||
this.circuitComponent = circuitComponent;
|
this.circuitComponent = circuitComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
VisualElement visualElement = new VisualElement(name).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory);
|
VisualElement visualElement = new VisualElement(node.getName()).setPos(new Vector(10, 10)).setShapeFactory(shapeFactory);
|
||||||
elementState.enter();
|
elementState.enter();
|
||||||
circuitComponent.setPartToInsert(visualElement);
|
circuitComponent.setPartToInsert(visualElement);
|
||||||
|
if (getIcon() == null) {
|
||||||
|
try {
|
||||||
|
node.getDescription();
|
||||||
|
setIcon(createIcon(node, shapeFactory));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorImportingModel")).addCause(ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
insertHistory.add(this);
|
insertHistory.add(this);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Imported importElement(File file) throws IOException {
|
public boolean isCustom() {
|
||||||
try {
|
return node.getDescriptionOrNull() instanceof ElementLibrary.ElementTypeDescriptionCustom;
|
||||||
LOGGER.debug("load element " + file);
|
|
||||||
Circuit circuit = Circuit.loadCircuit(file, shapeFactory);
|
|
||||||
ElementTypeDescriptionCustom description =
|
|
||||||
new ElementTypeDescriptionCustom(file,
|
|
||||||
attributes -> new CustomElement(circuit, library, file),
|
|
||||||
circuit.getAttributes(), circuit.getInputNames());
|
|
||||||
description.setShortName(createShortName(file));
|
|
||||||
library.addDescription(description, file);
|
|
||||||
|
|
||||||
InsertAction insertAction = new InsertAction(description, insertHistory, circuitComponent);
|
|
||||||
String descriptionText = circuit.getAttributes().get(Keys.DESCRIPTION);
|
|
||||||
if (descriptionText != null && descriptionText.length() > 0) {
|
|
||||||
insertAction.setToolTip(StringUtils.textToHTML(descriptionText));
|
|
||||||
description.setDescription(descriptionText);
|
|
||||||
}
|
|
||||||
|
|
||||||
JMenuItem menuEntry = insertAction.createJMenuItem();
|
|
||||||
ImportedItem item = findImportedItem(file);
|
|
||||||
if (item != null) {
|
|
||||||
if (customMenu != null) {
|
|
||||||
customMenu.remove(item.menuEntry);
|
|
||||||
}
|
|
||||||
importedElements.remove(item);
|
|
||||||
}
|
|
||||||
importedElements.add(new ImportedItem(file, menuEntry));
|
|
||||||
if (customMenu != null)
|
|
||||||
customMenu.add(menuEntry);
|
|
||||||
return new Imported(description, insertAction);
|
|
||||||
} catch (PinException e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImportedItem findImportedItem(File file) {
|
private static ImageIcon createIcon(LibraryNode node, ShapeFactory shapeFactory) {
|
||||||
for (ImportedItem i : importedElements) {
|
// don't load the description if only the icon is needed
|
||||||
if (i.file.equals(file))
|
// create action without an icon instead
|
||||||
return i;
|
if (node.isDescriptionLoaded()) {
|
||||||
|
try {
|
||||||
|
return new VisualElement(node.getDescription().getName()).setShapeFactory(shapeFactory).createIcon(75);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
SwingUtilities.invokeLater(new ErrorMessage(Lang.get("msg_errorImportingModel")).addCause(ex));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String createShortName(File file) {
|
|
||||||
return createShortName(file.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String createShortName(String name) {
|
|
||||||
if (name.endsWith(".dig")) return name.substring(0, name.length() - 4);
|
|
||||||
|
|
||||||
String transName = Lang.getNull("elem_" + name);
|
|
||||||
if (transName == null)
|
|
||||||
return name;
|
|
||||||
else
|
|
||||||
return transName;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static class ImportedItem {
|
|
||||||
private final File file;
|
|
||||||
private final JMenuItem menuEntry;
|
|
||||||
|
|
||||||
private ImportedItem(File file, JMenuItem menuEntry) {
|
|
||||||
this.file = file;
|
|
||||||
this.menuEntry = menuEntry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The description of a nested element.
|
|
||||||
* This is a complete circuit which is used as a element.
|
|
||||||
*/
|
|
||||||
public static class ElementTypeDescriptionCustom extends ElementTypeDescription {
|
|
||||||
private final File file;
|
|
||||||
private final ElementAttributes attributes;
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new element
|
|
||||||
*
|
|
||||||
* @param file the file which is loaded
|
|
||||||
* @param elementFactory a element factory which is used to create concrete elements if needed
|
|
||||||
* @param attributes the attributes of the element
|
|
||||||
* @param inputNames the names of the input signals
|
|
||||||
*/
|
|
||||||
public ElementTypeDescriptionCustom(File file, ElementFactory elementFactory, ElementAttributes attributes, PinDescription... inputNames) {
|
|
||||||
super(file.getPath().replace('\\', '/'), elementFactory, inputNames);
|
|
||||||
this.file = file;
|
|
||||||
this.attributes = attributes;
|
|
||||||
setShortName(file.getName());
|
|
||||||
addAttribute(Keys.ROTATE);
|
|
||||||
addAttribute(Keys.LABEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the filename
|
|
||||||
* the retuned file is opened if the user wants to modify the element
|
|
||||||
*
|
|
||||||
* @return the filename
|
|
||||||
*/
|
|
||||||
public File getFile() {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the elements attributes
|
|
||||||
*/
|
|
||||||
public ElementAttributes getAttributes() {
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a custom description for this field
|
|
||||||
*
|
|
||||||
* @param description the description
|
|
||||||
*/
|
|
||||||
public void setDescription(String description) {
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getDescription(ElementAttributes elementAttributes) {
|
|
||||||
if (description != null)
|
|
||||||
return description;
|
|
||||||
else
|
|
||||||
return super.getDescription(elementAttributes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static class Imported {
|
|
||||||
private final ElementTypeDescription description;
|
|
||||||
private final InsertAction insertAction;
|
|
||||||
|
|
||||||
private Imported(ElementTypeDescription description, InsertAction insertAction) {
|
|
||||||
this.description = description;
|
|
||||||
this.insertAction = insertAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
private State runModelMicroState;
|
private State runModelMicroState;
|
||||||
|
|
||||||
private Main() {
|
private Main() {
|
||||||
this(null, null, null);
|
this(null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,8 +137,8 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
* @param fileToOpen a file to open
|
* @param fileToOpen a file to open
|
||||||
* @param savedListener a listener which is notified if the file is changed on disk
|
* @param savedListener a listener which is notified if the file is changed on disk
|
||||||
*/
|
*/
|
||||||
public Main(Component parent, File fileToOpen, SavedListener savedListener) {
|
public Main(Component parent, File fileToOpen, SavedListener savedListener, ElementLibrary library) {
|
||||||
this(parent, fileToOpen, savedListener, null);
|
this(parent, fileToOpen, savedListener, library, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,7 +148,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
* @param circuit circuit to show
|
* @param circuit circuit to show
|
||||||
*/
|
*/
|
||||||
public Main(Component parent, Circuit circuit) {
|
public Main(Component parent, Circuit circuit) {
|
||||||
this(parent, null, null, circuit);
|
this(parent, null, null, null, circuit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,13 +159,14 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
* @param savedListener a listener which is notified if the file is changed on disk
|
* @param savedListener a listener which is notified if the file is changed on disk
|
||||||
* @param circuit circuit to show
|
* @param circuit circuit to show
|
||||||
*/
|
*/
|
||||||
private Main(Component parent, File fileToOpen, SavedListener savedListener, Circuit circuit) {
|
private Main(Component parent, File fileToOpen, SavedListener savedListener, ElementLibrary parentsLibrary, Circuit circuit) {
|
||||||
super(Lang.get("digital"));
|
super(Lang.get("digital"));
|
||||||
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
|
||||||
setIconImages(IconCreator.createImages("icon32.png", "icon64.png", "icon128.png"));
|
setIconImages(IconCreator.createImages("icon32.png", "icon64.png", "icon128.png"));
|
||||||
this.savedListener = savedListener;
|
this.savedListener = savedListener;
|
||||||
|
|
||||||
library = new ElementLibrary();
|
if (parentsLibrary == null) library = new ElementLibrary();
|
||||||
|
else this.library = parentsLibrary;
|
||||||
shapeFactory = new ShapeFactory(library, Settings.getInstance().get(Keys.SETTINGS_IEEE_SHAPES));
|
shapeFactory = new ShapeFactory(library, Settings.getInstance().get(Keys.SETTINGS_IEEE_SHAPES));
|
||||||
|
|
||||||
fileHistory = new FileHistory(this);
|
fileHistory = new FileHistory(this);
|
||||||
@ -276,8 +277,8 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
if (file == null)
|
if (file == null)
|
||||||
file = new File(name);
|
file = new File(name);
|
||||||
try {
|
try {
|
||||||
LibrarySelector.ElementTypeDescriptionCustom description =
|
ElementLibrary.ElementTypeDescriptionCustom description =
|
||||||
new LibrarySelector.ElementTypeDescriptionCustom(file,
|
new ElementLibrary.ElementTypeDescriptionCustom(file,
|
||||||
attributes -> new CustomElement(circuit, library, filename),
|
attributes -> new CustomElement(circuit, library, filename),
|
||||||
circuit.getAttributes(), circuit.getInputNames());
|
circuit.getAttributes(), circuit.getInputNames());
|
||||||
description.setShortName(name);
|
description.setShortName(name);
|
||||||
@ -319,7 +320,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
setFilename(null, true);
|
setFilename(null, true);
|
||||||
circuitComponent.setCircuit(new Circuit());
|
circuitComponent.setCircuit(new Circuit());
|
||||||
windowPosManager.closeAll();
|
windowPosManager.closeAll();
|
||||||
librarySelector.removeCustomElements();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.setActive(normalMode);
|
}.setActive(normalMode);
|
||||||
@ -330,7 +330,6 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
if (ClosingWindowListener.checkForSave(Main.this, Main.this)) {
|
if (ClosingWindowListener.checkForSave(Main.this, Main.this)) {
|
||||||
JFileChooser fc = getJFileChooser(lastFilename);
|
JFileChooser fc = getJFileChooser(lastFilename);
|
||||||
if (fc.showOpenDialog(Main.this) == JFileChooser.APPROVE_OPTION) {
|
if (fc.showOpenDialog(Main.this) == JFileChooser.APPROVE_OPTION) {
|
||||||
librarySelector.removeCustomElements();
|
|
||||||
loadFile(fc.getSelectedFile(), true);
|
loadFile(fc.getSelectedFile(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -342,7 +341,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
JFileChooser fc = getJFileChooser(lastFilename);
|
JFileChooser fc = getJFileChooser(lastFilename);
|
||||||
if (fc.showOpenDialog(Main.this) == JFileChooser.APPROVE_OPTION) {
|
if (fc.showOpenDialog(Main.this) == JFileChooser.APPROVE_OPTION) {
|
||||||
Main m = new Main(Main.this, fc.getSelectedFile(), null);
|
Main m = new Main(Main.this, fc.getSelectedFile(), null, null);
|
||||||
m.setLocationRelativeTo(Main.this);
|
m.setLocationRelativeTo(Main.this);
|
||||||
m.setVisible(true);
|
m.setVisible(true);
|
||||||
}
|
}
|
||||||
@ -399,7 +398,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
/**
|
/**
|
||||||
* Creates the edit menu
|
* Creates the edit menu
|
||||||
*
|
*
|
||||||
* @param menuBar the menu bar
|
* @param menuBar the menu bar
|
||||||
*/
|
*/
|
||||||
private void createEditMenu(JMenuBar menuBar) {
|
private void createEditMenu(JMenuBar menuBar) {
|
||||||
JMenu edit = new JMenu(Lang.get("menu_edit"));
|
JMenu edit = new JMenu(Lang.get("menu_edit"));
|
||||||
@ -496,7 +495,8 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the start menu
|
* Creates the start menu
|
||||||
* @param menuBar the menu bar
|
*
|
||||||
|
* @param menuBar the menu bar
|
||||||
* @param toolBar the tool bar
|
* @param toolBar the tool bar
|
||||||
*/
|
*/
|
||||||
private void createStartMenu(JMenuBar menuBar, JToolBar toolBar) {
|
private void createStartMenu(JMenuBar menuBar, JToolBar toolBar) {
|
||||||
@ -820,14 +820,13 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
@Override
|
@Override
|
||||||
public void open(File file) {
|
public void open(File file) {
|
||||||
if (ClosingWindowListener.checkForSave(Main.this, Main.this)) {
|
if (ClosingWindowListener.checkForSave(Main.this, Main.this)) {
|
||||||
librarySelector.removeCustomElements();
|
|
||||||
loadFile(file, true);
|
loadFile(file, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadFile(File filename, boolean toPrefs) {
|
private void loadFile(File filename, boolean toPrefs) {
|
||||||
try {
|
try {
|
||||||
librarySelector.setFilePath(filename.getParentFile());
|
library.setFilePath(filename.getParentFile());
|
||||||
Circuit circ = Circuit.loadCircuit(filename, shapeFactory);
|
Circuit circ = Circuit.loadCircuit(filename, shapeFactory);
|
||||||
circuitComponent.setCircuit(circ);
|
circuitComponent.setCircuit(circ);
|
||||||
stoppedState.enter();
|
stoppedState.enter();
|
||||||
@ -855,15 +854,21 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setFilename(File filename, boolean toPrefs) {
|
private void setFilename(File filename, boolean toPrefs) {
|
||||||
this.filename = filename;
|
try {
|
||||||
if (filename != null) {
|
this.filename = filename;
|
||||||
this.lastFilename = filename;
|
if (filename != null) {
|
||||||
librarySelector.setFilePath(filename.getParentFile());
|
this.lastFilename = filename;
|
||||||
if (toPrefs)
|
library.setFilePath(filename.getParentFile());
|
||||||
fileHistory.add(filename);
|
if (toPrefs)
|
||||||
setTitle(filename + " - " + Lang.get("digital"));
|
fileHistory.add(filename);
|
||||||
} else
|
setTitle(filename + " - " + Lang.get("digital"));
|
||||||
setTitle(Lang.get("digital"));
|
} else {
|
||||||
|
library.setFilePath(null);
|
||||||
|
setTitle(Lang.get("digital"));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
new ErrorMessage(Lang.get("msg_errorReadingFile")).addCause(e).show(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,7 +16,6 @@ import de.neemann.digital.draw.library.ElementLibrary;
|
|||||||
import de.neemann.digital.draw.library.ElementNotFoundException;
|
import de.neemann.digital.draw.library.ElementNotFoundException;
|
||||||
import de.neemann.digital.draw.shapes.Drawable;
|
import de.neemann.digital.draw.shapes.Drawable;
|
||||||
import de.neemann.digital.draw.shapes.ShapeFactory;
|
import de.neemann.digital.draw.shapes.ShapeFactory;
|
||||||
import de.neemann.digital.gui.LibrarySelector;
|
|
||||||
import de.neemann.digital.gui.Main;
|
import de.neemann.digital.gui.Main;
|
||||||
import de.neemann.digital.gui.SavedListener;
|
import de.neemann.digital.gui.SavedListener;
|
||||||
import de.neemann.digital.gui.sync.NoSync;
|
import de.neemann.digital.gui.sync.NoSync;
|
||||||
@ -562,20 +561,20 @@ public class CircuitComponent extends JComponent implements Circuit.ChangedListe
|
|||||||
Point p = new Point(e.getX(), e.getY());
|
Point p = new Point(e.getX(), e.getY());
|
||||||
SwingUtilities.convertPointToScreen(p, CircuitComponent.this);
|
SwingUtilities.convertPointToScreen(p, CircuitComponent.this);
|
||||||
AttributeDialog attributeDialog = new AttributeDialog(this, p, list, vp.getElementAttributes());
|
AttributeDialog attributeDialog = new AttributeDialog(this, p, list, vp.getElementAttributes());
|
||||||
if (elementType instanceof LibrarySelector.ElementTypeDescriptionCustom) {
|
if (elementType instanceof ElementLibrary.ElementTypeDescriptionCustom) {
|
||||||
attributeDialog.addButton(Lang.get("attr_openCircuitLabel"), new ToolTipAction(Lang.get("attr_openCircuit")) {
|
attributeDialog.addButton(Lang.get("attr_openCircuitLabel"), new ToolTipAction(Lang.get("attr_openCircuit")) {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
attributeDialog.dispose();
|
attributeDialog.dispose();
|
||||||
SwingUtilities.invokeLater(() -> new Main(CircuitComponent.this,
|
SwingUtilities.invokeLater(() -> new Main(CircuitComponent.this,
|
||||||
((LibrarySelector.ElementTypeDescriptionCustom) elementType).getFile(),
|
((ElementLibrary.ElementTypeDescriptionCustom) elementType).getFile(),
|
||||||
filename -> {
|
filename -> {
|
||||||
if (parentsSavedListener != null)
|
if (parentsSavedListener != null)
|
||||||
parentsSavedListener.saved(filename);
|
parentsSavedListener.saved(filename);
|
||||||
library.removeElement(filename);
|
library.removeElement(filename);
|
||||||
circuit.clearState();
|
circuit.clearState();
|
||||||
hasChanged();
|
hasChanged();
|
||||||
}).setVisible(true));
|
}, library).setVisible(true));
|
||||||
}
|
}
|
||||||
}.setToolTip(Lang.get("attr_openCircuit_tt")));
|
}.setToolTip(Lang.get("attr_openCircuit_tt")));
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,23 @@ public abstract class ToolTipAction extends AbstractAction {
|
|||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the icon
|
||||||
|
*
|
||||||
|
* @param icon the icon to set
|
||||||
|
*/
|
||||||
|
public void setIcon(Icon icon) {
|
||||||
|
putValue("SmallIcon", icon);
|
||||||
|
this.icon = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the icon
|
||||||
|
*/
|
||||||
|
public Icon getIcon() {
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the tool tip text
|
* Sets the tool tip text
|
||||||
*
|
*
|
||||||
|
@ -584,8 +584,8 @@ Es sind nur {1} Variablen erlaubt, es wurden jedoch {2} gefunden.</string>
|
|||||||
<string name="menu_fast_tt">Führt die Schaltung aus, bis ein Stopsignal über ein BRK-Element detektiert wird.</string>
|
<string name="menu_fast_tt">Führt die Schaltung aus, bis ein Stopsignal über ein BRK-Element detektiert wird.</string>
|
||||||
<string name="menu_file">Datei</string>
|
<string name="menu_file">Datei</string>
|
||||||
<string name="menu_help">Hilfe</string>
|
<string name="menu_help">Hilfe</string>
|
||||||
<string name="menu_import">Importieren</string>
|
<string name="menu_import">Aktualisieren</string>
|
||||||
<string name="menu_import_tt">Importiert eine Schaltung als verwendbares Bauteil</string>
|
<string name="menu_import_tt">Aktualisieren des Bauteile Menüs.</string>
|
||||||
<string name="menu_maximize">Einpassen</string>
|
<string name="menu_maximize">Einpassen</string>
|
||||||
<string name="menu_micro">Gatterschrittmodus</string>
|
<string name="menu_micro">Gatterschrittmodus</string>
|
||||||
<string name="menu_micro_tt">Startet die Schaltung im Gatterschrittmodus</string>
|
<string name="menu_micro_tt">Startet die Schaltung im Gatterschrittmodus</string>
|
||||||
|
@ -571,8 +571,8 @@ allowed are {1} variables but {2} are found.</string>
|
|||||||
<string name="menu_fast_tt">Runs the circuit until a break is detected by the BRK component.</string>
|
<string name="menu_fast_tt">Runs the circuit until a break is detected by the BRK component.</string>
|
||||||
<string name="menu_file">File</string>
|
<string name="menu_file">File</string>
|
||||||
<string name="menu_help">Help</string>
|
<string name="menu_help">Help</string>
|
||||||
<string name="menu_import">Import</string>
|
<string name="menu_import">Update</string>
|
||||||
<string name="menu_import_tt">Imports a circuit as a usable component!</string>
|
<string name="menu_import_tt">Updates the components menu!</string>
|
||||||
<string name="menu_maximize">Fit to window</string>
|
<string name="menu_maximize">Fit to window</string>
|
||||||
<string name="menu_micro">Single gate stepping</string>
|
<string name="menu_micro">Single gate stepping</string>
|
||||||
<string name="menu_micro_tt">Runs the circuit in single gate step mode</string>
|
<string name="menu_micro_tt">Runs the circuit in single gate step mode</string>
|
||||||
|
@ -64,8 +64,7 @@ public class TestNesting extends TestCase {
|
|||||||
|
|
||||||
private TestExecuter createTestExecuterForNesting(String file) throws IOException, NodeException, PinException, ElementNotFoundException {
|
private TestExecuter createTestExecuterForNesting(String file) throws IOException, NodeException, PinException, ElementNotFoundException {
|
||||||
ElementLibrary library = new ElementLibrary();
|
ElementLibrary library = new ElementLibrary();
|
||||||
LibrarySelector librarySelector = new LibrarySelector(library, new ShapeFactory(library), null);
|
library.setFilePath(new File(Resources.getRoot(), "dig"));
|
||||||
librarySelector.setFilePath(new File(Resources.getRoot(), "dig"));
|
|
||||||
return TestExecuter.createFromFile(file, library);
|
return TestExecuter.createFromFile(file, library);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,10 +70,9 @@ public class ToBreakRunner {
|
|||||||
|
|
||||||
private ToBreakRunner(File filename, boolean doInit) throws IOException, PinException, NodeException, ElementNotFoundException {
|
private ToBreakRunner(File filename, boolean doInit) throws IOException, PinException, NodeException, ElementNotFoundException {
|
||||||
library = new ElementLibrary();
|
library = new ElementLibrary();
|
||||||
|
library.setFilePath(filename.getParentFile());
|
||||||
ShapeFactory shapeFactory = new ShapeFactory(library);
|
ShapeFactory shapeFactory = new ShapeFactory(library);
|
||||||
circuit = Circuit.loadCircuit(filename, shapeFactory);
|
circuit = Circuit.loadCircuit(filename, shapeFactory);
|
||||||
LibrarySelector librarySelector = new LibrarySelector(library, shapeFactory, null);
|
|
||||||
librarySelector.setFilePath(filename.getParentFile());
|
|
||||||
|
|
||||||
ModelCreator md = new ModelCreator(circuit, library);
|
ModelCreator md = new ModelCreator(circuit, library);
|
||||||
model = md.createModel(false);
|
model = md.createModel(false);
|
||||||
|
@ -23,6 +23,7 @@ public class TestElemConsistence extends TestCase {
|
|||||||
* @throws NodeException
|
* @throws NodeException
|
||||||
*/
|
*/
|
||||||
public void testConsistence() throws NodeException, PinException {
|
public void testConsistence() throws NodeException, PinException {
|
||||||
|
/*
|
||||||
ElementLibrary library = new ElementLibrary();
|
ElementLibrary library = new ElementLibrary();
|
||||||
for (ElementLibrary.ElementContainer e : library) {
|
for (ElementLibrary.ElementContainer e : library) {
|
||||||
ElementTypeDescription etd = e.getDescription();
|
ElementTypeDescription etd = e.getDescription();
|
||||||
@ -37,7 +38,7 @@ public class TestElemConsistence extends TestCase {
|
|||||||
checkPins(key, etd.getInputDescription(new ElementAttributes()));
|
checkPins(key, etd.getInputDescription(new ElementAttributes()));
|
||||||
checkPins(key, etd.getOutputDescriptions(new ElementAttributes()));
|
checkPins(key, etd.getOutputDescriptions(new ElementAttributes()));
|
||||||
}
|
}
|
||||||
}
|
}*/ fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkPins(String key, PinDescriptions pins) {
|
private void checkPins(String key, PinDescriptions pins) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user