mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5944f4d36f | |||
| 4fb17d343d | |||
| 144f6e1c9f | |||
| c9252f7c98 |
@@ -14,10 +14,10 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up JDK 21
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '21'
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
cache: maven
|
||||
|
||||
|
||||
Vendored
+1
-2
@@ -1,4 +1,3 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "disabled",
|
||||
"java.compile.nullAnalysis.mode": "disabled"
|
||||
"java.configuration.updateBuildConfiguration": "interactive"
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
# DIY Layout Creator — repository map
|
||||
|
||||
The guidelines that govern all code changes live in **[`diylc/CLAUDE.md`](diylc/CLAUDE.md)**. Read
|
||||
that file before editing anything under `diylc/`.
|
||||
|
||||
## What is where
|
||||
|
||||
| Path | Contents |
|
||||
| --- | --- |
|
||||
| `diylc/` | The application. Maven reactor with `diylc-core`, `diylc-library`, `diylc-swing`. This is where nearly all work happens. |
|
||||
| `diylc-regression-data/` | Sample `.diy` projects plus reference PNG and netlist outputs used by the regression suite, and the historical reports. |
|
||||
| `diylc-server-api/` | PHP backend for cloud and collaboration features. Runs in an isolated environment on diy-fever.com and cannot be tested locally — do not modify unless explicitly asked. |
|
||||
| `snap/` | Snap packaging metadata. |
|
||||
|
||||
## House rules that apply repository-wide
|
||||
|
||||
- Match the conventions of the surrounding code; consistency beats novelty.
|
||||
- Comment only what the code cannot say for itself. No comments that restate the line below them.
|
||||
- Every new source file begins with the GPL header from `diylc/HEADER.txt`.
|
||||
- Do not commit or push. Leave changes in the working tree for review.
|
||||
|
||||
The project is GPLv3; see `COPYING`.
|
||||
@@ -1,93 +1,63 @@
|
||||
### 🛠️ Introduction
|
||||
<h3><a name="News"></a>Introduction<a href="#Introduction" class="section_anchor"></a></h3>
|
||||
<p align="justify">
|
||||
DIY Layout Creator (DIYLC) is a specialized software tool designed for hobbyists and electronics enthusiasts to create circuit layouts on stripboard, perfboard, PCB, and point-to-point wiring. It provides an intuitive, drag-and-drop interface for placing components, arranging connections, and visualizing circuit designs before assembly. With a built-in component library and customization options, it allows users to design layouts with precision and clarity. The software is particularly useful for designing, analyzing, and debugging guitar wiring diagrams, helping musicians and builders plan and troubleshoot custom wiring configurations for pickups, switches, and controls. Its versatility makes it an ideal solution for DIY electronics projects, prototyping, and documentation.</p>
|
||||
<br>
|
||||
<a href="https://github.com/bancika/diy-layout-creator/releases/latest">Click here</a> to get the latest version for all platforms.</a><br>
|
||||
<a href="https://github.com/bancika/diy-layout-creator/tree/wiki">Click here</a> to read the user documentation as well as developer documentation.<br>
|
||||
<br>
|
||||
<b>Mac users</b>: in most instances, the Gatekeeper will block DIYLC and mark it as damaged because it's a 3rd party app from an independent vendor (me). <a href="[https://support.apple.com/en-us/HT202491](https://support.apple.com/kb/ph18657?locale=en_US)">This document</a> covers how to allow DIYLC on your Mac.
|
||||
|
||||
DIY Layout Creator (DIYLC) is a specialized software tool designed for hobbyists and electronics enthusiasts to create circuit layouts on stripboard, perfboard, PCB, and point-to-point wiring.
|
||||
<h3><a name="Samples"></a>Samples<a href="#Samples" class="section_anchor"></a></h3>
|
||||
|
||||
It provides an intuitive, drag-and-drop interface for placing components, arranging connections, and visualizing circuit designs before assembly. With a built-in component library and customization options, it allows users to design layouts with precision and clarity.
|
||||
<h4>Point-to-point tube amplifier</h4>
|
||||
<p align="center"><a href="http://diy-fever.com/wordpress/wp-content/gallery/diylc/slo.png" rel="nofollow"><img src="https://diy-fever.com/wordpress/wp-content/gallery/diylc/cache/slo.png-nggid041072-ngg0dyn-450x350-00f0w010c010r110f110r010t010.png"></a></p>
|
||||
<h4>Guitar wiring</h4>
|
||||
<p align="center"><a href="http://diy-fever.com/wordpress/wp-content/gallery/diylc/travelcaster.png" rel="nofollow"><img src="https://diy-fever.com/nextgen-image/1073/450x350/34b70d759e46422208d61e376b4633dc"></a></p>
|
||||
<h4>PCB tube amplifier</h4>
|
||||
<p align="center"><a href="http://diy-fever.com/wordpress/wp-content/gallery/diylc/iic.png" rel="nofollow"><img src="https://diy-fever.com/nextgen-image/1070/450x350/ccb592ec5828b6f5bc75e840438918f1"></a></p>
|
||||
<h4>Perfboard guitar effect</h4>
|
||||
<p align="center"><a href="http://diy-fever.com/wordpress/wp-content/gallery/diylc/split.png" rel="nofollow"><img src="https://diy-fever.com/nextgen-image/1069/450x350/358e43165de40e9c4043726c9efde4a7"></a></p>
|
||||
|
||||
🎸 **Perfect for guitar pedal builders, guitar, synth, audio and HAM enthusiasts!** DIYLC is particularly useful for designing, analyzing, and debugging guitar wiring diagrams, helping musicians and builders plan and troubleshoot custom wiring configurations for pickups, switches, and controls. Its versatility makes it an ideal solution for DIY electronics projects, prototyping, and documentation.
|
||||
|
||||
### 🚀 Quick Links
|
||||
* **[⬇️ Download the latest release](https://github.com/bancika/diy-layout-creator/releases/latest)** for all platforms.
|
||||
* **[📄 Read the Wiki](https://github.com/bancika/diy-layout-creator/tree/wiki)** for free user and developer documentation.
|
||||
|
||||
> 🍎 **Mac users:** Gatekeeper may block DIYLC since it's from an independent developer. [Read this guide](https://support.apple.com/kb/ph18657?locale=en_US) on how to easily allow DIYLC on your Mac.
|
||||
|
||||
---
|
||||
|
||||
### 📖 The Official DIYLC Guide
|
||||
|
||||
<a href="https://www.diy-fever.com/diylc-book">
|
||||
<img src="https://www.diy-fever.com/diylc/book/book_v1_thumb.png" alt="DIYLC Official Guide" width="220" align="left" style="margin-right: 20px; margin-bottom: 20px;">
|
||||
</a>
|
||||
|
||||
**Master DIY Layout Creator and streamline your design workflow!**
|
||||
|
||||
The **Official DIYLC Guide (v1.0)** is a comprehensive 174-page eBook that goes way beyond the basics. It features step-by-step design workflows for everything from multi-layer PCBs to hot-rodded point-to-point tube amps. Learn to master advanced tools like the Virtual Multimeter, Netlist generation, the Guitar Wiring Analyzer, and the new AI Assistant.
|
||||
|
||||
👉 **[Click here to grab your copy!](https://www.diy-fever.com/diylc-book)**
|
||||
|
||||
*Active Patreon supporters get an additional 50% off or a completely free copy. Check the [Patreon feed](https://www.patreon.com/c/user?u=5213116) for your VIP link!*
|
||||
|
||||
<br clear="all">
|
||||
|
||||
---
|
||||
|
||||
### 🖼️ Gallery & Samples
|
||||
|
||||
<p align="center">
|
||||
<img src="https://diy-fever.com/wordpress/wp-content/gallery/diylc/slo.png" width="48%" alt="Point-to-point tube amplifier">
|
||||
<img src="https://diy-fever.com/wordpress/wp-content/gallery/diylc/travelcaster.png" width="48%" alt="Guitar wiring">
|
||||
<br>
|
||||
<sup><i>Left: Point-to-point tube amplifier | Right: Guitar wiring</i></sup>
|
||||
<br><br>
|
||||
<img src="https://diy-fever.com/wordpress/wp-content/gallery/diylc/iic.png" width="48%" alt="PCB tube amplifier">
|
||||
<img src="https://diy-fever.com/wordpress/wp-content/gallery/diylc/split.png" width="48%" alt="Perfboard guitar effect">
|
||||
<br>
|
||||
<sup><i>Left: PCB tube amplifier | Right: Perfboard guitar effect</i></sup>
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
### ✨ Key Features
|
||||
* 🆓 **Free for Life**: A true old-school offline app—the app you download is yours forever and the files you created are yours.
|
||||
* 💻 **Platform Independence:** Runs locally on any machine capable of running Java JRE/JDK 21 or newer.
|
||||
* 🖱️ **Intuitive UI:** Easy-to-use interface; most operations can be done seamlessly with a mouse.
|
||||
* 🎛️ **Versatile Designs:** Draw PCB, perfboard, stripboard, or point-to-point layouts, schematics, guitar wiring diagrams or custom faceplates.
|
||||
* 🔌 **Highly Extensible:** API allows custom plug-ins and new components to be added easily.
|
||||
* 🚀 **Optimized:** Improved performance and reduced memory consumption.
|
||||
* 💾 **Smart Defaults:** Save default values individually for each component property.
|
||||
* 🖨️ **Export Options:** Export outputs to image, PDF, or printer.
|
||||
* 📄 **Toner Transfer & Gerber:** Export PCB trace masks for toner transfer or Gerber files for fabrication.
|
||||
* 📋 **Bill of Materials:** Create a BOM within the project or export to multiple file formats.
|
||||
* 🔍 **Guitar Wiring Analysis:** Analyze guitar wirings and visualize detailed pickup configurations for each switch state.
|
||||
* ☁️ **Cloud Integration:** Share your projects, search the cloud, and download other users' designs.
|
||||
* 🤖 **AI Powered:** Features a built-in AI assistant to help answer general electronics questions, guide you through DIYLC's usability, and provide insights or troubleshooting for the specific circuit you are designing.
|
||||
* ⚡ **Circuit Analysis:** Various tools aimed to help you debug and analyze your circuits.
|
||||
* 📈 **SPICE Netlists:** Export circuits directly to SPICE-compatible netlists.
|
||||
|
||||
---
|
||||
|
||||
### 🐛 Support & Community
|
||||
* **Found a bug or have a feature request?** Head over to the [Issues page](https://github.com/bancika/diy-layout-creator/issues) to open a ticket.
|
||||
* **Need technical assistance or want to chat?** Join the discussion in our [Google Group](http://groups.google.com/group/diy-layout-creator).
|
||||
|
||||
---
|
||||
|
||||
### ❤️ Want to contribute?
|
||||
DIYLC is provided free of charge and can be used and redistributed freely. Building, testing, and maintaining this tool—while supporting our growing community—takes a significant amount of time and effort.
|
||||
|
||||
If you find DIYLC useful, here are the best ways you can support its future development:
|
||||
* 🧡 **[Become a Patreon](https://www.patreon.com/c/user?u=5213116):** Join the inner circle for exclusive perks.
|
||||
* 📖 **[Purchase the Official DIYLC Guide](https://www.diy-fever.com/diylc-book):** Level up your layout skills while directly supporting the app!
|
||||
* ☕ **[Make a PayPal donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=U6GLS8HLTSU88):** A one-time donation helps keep the lights on.
|
||||
* 📝 **Documentation:** Help us improve the [user manual](https://github.com/bancika/diy-layout-creator/blob/wiki/Manual.md) or other project docs.
|
||||
* 🧩 **Extend the App:** Read the [Component API Wiki](https://github.com/bancika/diy-layout-creator/blob/wiki/ComponentAPI.md) to add new components, or the [Plugin API Wiki](https://github.com/bancika/diy-layout-creator/blob/wiki/PluginAPI.md) to create new plug-ins.
|
||||
|
||||
---
|
||||
|
||||
### 📜 License Information
|
||||
The source code is released under the [GNU General Public License version 3](https://www.gnu.org/licenses/gpl-3.0.txt). Please contact the project owner to obtain a commercial license if you plan to use the source code, or any part of it, for commercial purposes.
|
||||
|
||||
### 🙌 Credits
|
||||
* Huge thanks to the online communities that contributed ideas and helped test the app: [DIY Stompboxes](http://www.diystompboxes.com/smfforum/), [AX84](http://ax84.com/bbs), and [Free Stompboxes](http://freestompboxes.org).
|
||||
* DIYLC is highly optimized thanks to [YourKit Java Profiler](http://www.yourkit.com/java/profiler/index.jsp). YourKit is kindly supporting open-source projects with its full-featured Java Profiler, which helped tremendously with memory and performance profiling. *YourKit, LLC is the creator of innovative and intelligent tools for profiling Java and .NET applications.*
|
||||
<h3><a name="Key Features"></a>Features<a href="#Features" class="section_anchor"></a></h3>
|
||||
<ul>
|
||||
<li>platform independence, will run on any machine having Java JRE/JDK 8 or newer </li>
|
||||
<li>easy to use interface, most of the operations can be done using mouse </li>
|
||||
<li>draw PCB, perfboard, stripboard or point-to-point circuit layouts layouts, schematics and guitar wiring diagrams </li>
|
||||
<li>high flexibility, has the API to allow plug-ins and new components to be added</li>
|
||||
<li>improved performance and reduced memory consumption compared to the previous versions </li>
|
||||
<li>save default values for each property of a component individually </li>
|
||||
<li>group components together and treat them as one, e.g. move, edit or delete </li>
|
||||
<li>export the output to image, PDF or printer </li>
|
||||
<li>export PCB trace mask suitable for toner transfer </li>
|
||||
<li>export PCB designs to Gerber for fabrication </li>
|
||||
<li>create a Bill of Materials as a part of the project or export it to few different file formats </li>
|
||||
<li>analyze guitar wirings and show detailed pickup configuration in each switch configuration</li>
|
||||
<li>zoom in/out feature </li>
|
||||
<li>configurable grid spacing on the project level </li>
|
||||
<li>auto update checks for new versions </li>
|
||||
<li>import files created with older versions of the application </li>
|
||||
<li>cloud feature - share your projects, search through the cloud and download other users' projects </li>
|
||||
<li>highlight connected areas to simplify validation and circuit debugging</li>
|
||||
<li>analyze guitar wiring diagrams and visualize pickup wirings for each switch configuration</li>
|
||||
<li>export circuits to SPICE-compatible netlists</li>
|
||||
</ul>
|
||||
<p>To report bugs or request a new feature go to <a href="https://github.com/bancika/diy-layout-creator/issues" rel="nofollow">Issues</a> page and create a new issue describing your problem or request. </p>
|
||||
<p>To join the discussion or request technical assistance, use the dedicated <a href="http://groups.google.com/group/diy-layout-creator" rel="nofollow">Discussion Group</a>. </p>
|
||||
<h3><a name="Want_to_contribute?"></a>Want to contribute?<a href="#Want_to_contribute?" class="section_anchor"></a></h3>
|
||||
<p align="justify"><strong>DIYLC is provided free of charge and can be used and redistributed freely. Please note that it takes a lot of time and effort to build, test and maintain it and to interact with the growing community of users. If you find DIYLC useful and want to support further development, these are some of the ways you can contribute</strong></p>
|
||||
<ul>
|
||||
<li><a href="https://www.patreon.com/c/user?u=5213116">Become a Patreon.</a></li>
|
||||
<li><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=U6GLS8HLTSU88">Make a one-time donation with PayPal.</a></li>
|
||||
<li>Help with adding the information to the <a href="https://github.com/bancika/diy-layout-creator/blob/wiki/Manual.md">user manual</a> or other project documentation.</li>
|
||||
<li>Extend the component base, read <a href="https://github.com/bancika/diy-layout-creator/blob/wiki/ComponentAPI.md" rel="nofollow">this wiki</a> to learn how to create new components. </li>
|
||||
<li>Add a new functionality though plug-ins, read <a href="https://github.com/bancika/diy-layout-creator/blob/wiki/PluginAPI.md" rel="nofollow">this wiki</a> to learn how to create new plug-ins. </li>
|
||||
</ul>
|
||||
<!--<p align="center"><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=U6GLS8HLTSU88" rel="nofollow"><img src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif"></a> </p>-->
|
||||
<h3><a name="License_information"></a>License information<a href="#License_information" class="section_anchor"></a></h3>
|
||||
<p>Source code is released under <a href="https://www.gnu.org/licenses/gpl-3.0.txt">GNU General Public License version 3</a>. Contact the project owner to obtain a license in case you plan to use the source code, or any part of it, in commercial purposes. </p>
|
||||
<p></p>
|
||||
<h3><a name="Credits"></a>Credits<a href="#Credits" class="section_anchor"></a></h3>
|
||||
<ul>
|
||||
<li>Big thanks goes to folks from the following online communities for contributing ideas and helped test the app: <a href="http://www.diystompboxes.com/smfforum/" rel="nofollow">DIY Stompboxes</a>, <a href="http://ax84.com/bbs" rel="nofollow">AX84</a> and <a href="http://freestompboxes.org" rel="nofollow">Free Stompboxes</a>. </li>
|
||||
<li>I'm happy to report that DIYLC 4 is the fastest version ever. <a href="http://www.yourkit.com/java/profiler/index.jsp" rel="nofollow">YourKit Java Profiler</a> helped tremendously with memory and performance profiling and pointed me to places in the code that took longer to run or consumed more memory than I'd like them to. I strongly recommend this tool to anyone developing Java or .NET applications because it helps finding bottlenecks and allocation hot-spots very fast.<br><br>YourKit is kindly supporting open source projects with its full-featured Java Profiler.<br>YourKit, LLC is the creator of innovative and intelligent tools for profiling Java and .NET applications.<br>Take a look at YourKit's leading software products: <a href="http://www.yourkit.com/java/profiler/index.jsp" rel="nofollow">YourKit Java Profiler</a> and <a href="http://www.yourkit.com/.net/profiler/index.jsp" rel="nofollow">YourKit .NET Profiler</a> </li>
|
||||
</ul>
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<project>
|
||||
<fileVersion>
|
||||
<major>5</major>
|
||||
<minor>5</minor>
|
||||
<build>0</build>
|
||||
</fileVersion>
|
||||
<title>New Project</title>
|
||||
<author>branislavstojkovic</author>
|
||||
<width value="29.0" unit="cm"/>
|
||||
<height value="21.0" unit="cm"/>
|
||||
<gridSpacing value="0.1" unit="in"/>
|
||||
<dotSpacing>1</dotSpacing>
|
||||
<components>
|
||||
<diylc.connectivity.CopperTrace>
|
||||
<name>Trace1</name>
|
||||
<alpha>127</alpha>
|
||||
<points>
|
||||
<point x="5.9" y="3.4"/>
|
||||
<point x="6.4" y="3.4"/>
|
||||
<point x="6.15" y="3.4"/>
|
||||
</points>
|
||||
<bodyColor hex="ffffff"/>
|
||||
<borderColor hex="000000"/>
|
||||
<labelColor hex="000000"/>
|
||||
<leadColor hex="000000"/>
|
||||
<display>NAME</display>
|
||||
<flipStanding>false</flipStanding>
|
||||
<labelOriantation>Directional</labelOriantation>
|
||||
<moveLabel>false</moveLabel>
|
||||
<hideShortLeads>false</hideShortLeads>
|
||||
<thickness value="1.0" unit="mm"/>
|
||||
<layer>_1</layer>
|
||||
</diylc.connectivity.CopperTrace>
|
||||
<diylc.connectivity.CopperTrace>
|
||||
<name>Trace2</name>
|
||||
<alpha>127</alpha>
|
||||
<points>
|
||||
<point x="6.005" y="3.45"/>
|
||||
<point x="6.305" y="3.45"/>
|
||||
<point x="6.155" y="3.45"/>
|
||||
</points>
|
||||
<bodyColor hex="ffffff"/>
|
||||
<borderColor hex="000000"/>
|
||||
<labelColor hex="000000"/>
|
||||
<leadColor hex="000000"/>
|
||||
<display>NAME</display>
|
||||
<flipStanding>false</flipStanding>
|
||||
<labelOriantation>Directional</labelOriantation>
|
||||
<moveLabel>false</moveLabel>
|
||||
<hideShortLeads>false</hideShortLeads>
|
||||
<thickness value="1.0" unit="mm"/>
|
||||
<layer>_1</layer>
|
||||
</diylc.connectivity.CopperTrace>
|
||||
<diylc.connectivity.SolderPad>
|
||||
<name>Pad1</name>
|
||||
<alpha>127</alpha>
|
||||
<size value="0.09" unit="in"/>
|
||||
<color hex="000000"/>
|
||||
<point x="5.9" y="3.4"/>
|
||||
<type>ROUND</type>
|
||||
<holeSize value="0.8" unit="mm"/>
|
||||
<layer>_1</layer>
|
||||
<holeType>NTPH</holeType>
|
||||
</diylc.connectivity.SolderPad>
|
||||
<diylc.connectivity.SolderPad>
|
||||
<name>Pad2</name>
|
||||
<alpha>127</alpha>
|
||||
<size value="0.09" unit="in"/>
|
||||
<color hex="000000"/>
|
||||
<point x="6.4" y="3.4"/>
|
||||
<type>ROUND</type>
|
||||
<holeSize value="0.8" unit="mm"/>
|
||||
<layer>_1</layer>
|
||||
<holeType>NTPH</holeType>
|
||||
</diylc.connectivity.SolderPad>
|
||||
</components>
|
||||
<groups/>
|
||||
<lockedLayers/>
|
||||
<lockedComponents/>
|
||||
<hiddenLayers/>
|
||||
<font name="Dialog" size="14" style="0"/>
|
||||
</project>
|
||||
@@ -0,0 +1,534 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<project>
|
||||
<fileVersion>
|
||||
<major>5</major>
|
||||
<minor>5</minor>
|
||||
<build>0</build>
|
||||
</fileVersion>
|
||||
<title>New Project</title>
|
||||
<author>bancika</author>
|
||||
<width value="10.0" unit="cm"/>
|
||||
<height value="14.0" unit="cm"/>
|
||||
<gridSpacing value="0.1" unit="in"/>
|
||||
<dotSpacing>1</dotSpacing>
|
||||
<components>
|
||||
<diylc.passive.PotentiometerPanel>
|
||||
<name>Volume</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints>
|
||||
<point x="1.8" y="4.5"/>
|
||||
<point x="2.0" y="4.5"/>
|
||||
<point x="2.2" y="4.5"/>
|
||||
</controlPoints>
|
||||
<resistance value="250.0" unit="K"/>
|
||||
<orientation>DEFAULT</orientation>
|
||||
<taper>LOG</taper>
|
||||
<bodyDiameter value="16.0" unit="mm"/>
|
||||
<spacing value="0.2" unit="in"/>
|
||||
<lugDiameter value="0.15" unit="in"/>
|
||||
<bodyColor hex="b6b6b6"/>
|
||||
<borderColor hex="808080"/>
|
||||
<nutColor hex="cbd5db"/>
|
||||
<waferColor hex="cd8500"/>
|
||||
<type>ThroughHole</type>
|
||||
<showShaft>false</showShaft>
|
||||
<view>ShaftDown</view>
|
||||
</diylc.passive.PotentiometerPanel>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W7</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="1.9" y="2.5"/>
|
||||
<point x="1.5" y="3.6"/>
|
||||
<point x="1.0" y="3.9"/>
|
||||
<point x="1.8" y="4.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="cc00cc"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.guitar.SingleCoilPickup>
|
||||
<name>Neck</name>
|
||||
<alpha>127</alpha>
|
||||
<value>Chopper</value>
|
||||
<orientation>_90</orientation>
|
||||
<controlPoint x="3.0" y="2.4"/>
|
||||
<controlPoints>
|
||||
<point x="3.0" y="2.4"/>
|
||||
<point x="3.0" y="2.3"/>
|
||||
<point x="3.0" y="2.2"/>
|
||||
<point x="3.0" y="2.1"/>
|
||||
</controlPoints>
|
||||
<polarity>Humbucking</polarity>
|
||||
<labelColor hex="ffffff"/>
|
||||
<color hex="666666"/>
|
||||
<poleColor hex="333333"/>
|
||||
<baseColor hex="666666"/>
|
||||
<type>Stratocaster</type>
|
||||
<polePieceType>RailHumbucker</polePieceType>
|
||||
<lugColor hex="e0c04c"/>
|
||||
</diylc.guitar.SingleCoilPickup>
|
||||
<diylc.guitar.SingleCoilPickup>
|
||||
<name>Bridge</name>
|
||||
<alpha>127</alpha>
|
||||
<value></value>
|
||||
<orientation>_270</orientation>
|
||||
<controlPoint x="0.8" y="2.1"/>
|
||||
<controlPoints>
|
||||
<point x="0.8" y="2.1"/>
|
||||
<point x="0.8" y="2.2"/>
|
||||
<point x="0.8" y="2.3"/>
|
||||
<point x="0.8" y="2.4"/>
|
||||
</controlPoints>
|
||||
<polarity>Humbucking</polarity>
|
||||
<labelColor hex="ffffff"/>
|
||||
<color hex="666666"/>
|
||||
<poleColor hex="333333"/>
|
||||
<baseColor hex="666666"/>
|
||||
<type>Stratocaster</type>
|
||||
<polePieceType>RailHumbucker</polePieceType>
|
||||
<lugColor hex="e0c04c"/>
|
||||
</diylc.guitar.SingleCoilPickup>
|
||||
<diylc.guitar.LPSwitch>
|
||||
<name>SW1</name>
|
||||
<alpha>127</alpha>
|
||||
<value></value>
|
||||
<controlPoints>
|
||||
<point x="1.9" y="1.2"/>
|
||||
<point x="1.7" y="2.495"/>
|
||||
<point x="1.9" y="2.495"/>
|
||||
<point x="2.1" y="2.495"/>
|
||||
</controlPoints>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.guitar.LPSwitch>
|
||||
<diylc.electromechanical.MiniToggleSwitch>
|
||||
<name defined-in="diylc.AbstractComponent">Split</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints>
|
||||
<point x="1.9" y="3.5"/>
|
||||
<point x="1.9" y="3.7"/>
|
||||
<point x="1.9" y="3.9"/>
|
||||
<point x="2.1" y="3.5"/>
|
||||
<point x="2.1" y="3.7"/>
|
||||
<point x="2.1" y="3.9"/>
|
||||
</controlPoints>
|
||||
<switchType>DPDT</switchType>
|
||||
<orientation>VERTICAL</orientation>
|
||||
<spacing value="0.2" unit="in"/>
|
||||
<bodyColor hex="3299cc"/>
|
||||
<borderColor hex="236b8e"/>
|
||||
<terminalPadColor hex="287ba4"/>
|
||||
<terminalColor hex="eeeeee"/>
|
||||
<showMarkers>false</showMarkers>
|
||||
</diylc.electromechanical.MiniToggleSwitch>
|
||||
<diylc.electromechanical.OpenJack1__4>
|
||||
<name>J1</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints>
|
||||
<point x="2.7" y="4.9"/>
|
||||
<point x="2.9" y="4.5"/>
|
||||
<point x="3.6" y="4.6"/>
|
||||
</controlPoints>
|
||||
<orientation>_270</orientation>
|
||||
<angle>270</angle>
|
||||
<type>MONO</type>
|
||||
<showLabels>true</showLabels>
|
||||
</diylc.electromechanical.OpenJack1__4>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W2</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.3"/>
|
||||
<point x="1.2" y="2.6"/>
|
||||
<point x="1.7" y="3.4"/>
|
||||
<point x="1.9" y="3.7"/>
|
||||
</controlPoints2>
|
||||
<color hex="ffffff"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W2</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.2"/>
|
||||
<point x="1.5" y="2.6"/>
|
||||
<point x="1.7" y="3.5"/>
|
||||
<point x="1.9" y="3.7"/>
|
||||
</controlPoints2>
|
||||
<color hex="666666"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.4"/>
|
||||
<point x="1.0" y="4.1"/>
|
||||
<point x="2.1" y="4.6"/>
|
||||
<point x="2.2" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="3.0" y="2.3"/>
|
||||
<point x="2.4" y="3.0"/>
|
||||
<point x="2.8" y="4.0"/>
|
||||
<point x="2.2" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="666666"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W4</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.1"/>
|
||||
<point x="1.1" y="2.3"/>
|
||||
<point x="1.4" y="2.7"/>
|
||||
<point x="1.7" y="2.6"/>
|
||||
</controlPoints2>
|
||||
<color hex="ff0000"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.2" y="4.1"/>
|
||||
<point x="2.7" y="4.2"/>
|
||||
<point x="2.3" y="4.6"/>
|
||||
<point x="2.9" y="4.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.0" y="4.5"/>
|
||||
<point x="2.3" y="4.7"/>
|
||||
<point x="2.3" y="5.1"/>
|
||||
<point x="2.7" y="4.9"/>
|
||||
</controlPoints2>
|
||||
<color hex="ff0000"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W5</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.1" y="3.9"/>
|
||||
<point x="2.2" y="3.9"/>
|
||||
<point x="2.3" y="4.0"/>
|
||||
<point x="2.2" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W6</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="1.9" y="3.9"/>
|
||||
<point x="1.9" y="3.8"/>
|
||||
<point x="2.1" y="3.8"/>
|
||||
<point x="2.1" y="3.9"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="3.0" y="2.2"/>
|
||||
<point x="2.6" y="2.6"/>
|
||||
<point x="2.1" y="2.6"/>
|
||||
<point x="2.1" y="2.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="ffffff"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W4</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.1" y="3.7"/>
|
||||
<point x="2.2" y="3.5"/>
|
||||
<point x="2.5" y="3.2"/>
|
||||
<point x="3.0" y="2.4"/>
|
||||
</controlPoints2>
|
||||
<color hex="ff0000"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W6</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.1" y="3.7"/>
|
||||
<point x="2.3" y="3.5"/>
|
||||
<point x="2.7" y="2.1"/>
|
||||
<point x="3.0" y="2.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.passive.AxialFilmCapacitor>
|
||||
<name>Cbleed</name>
|
||||
<alpha>127</alpha>
|
||||
<length value="0.4" unit="in"/>
|
||||
<width value="0.125" unit="in"/>
|
||||
<points>
|
||||
<point x="1.8" y="4.5"/>
|
||||
<point x="2.0" y="4.5"/>
|
||||
<point x="1.9" y="4.5"/>
|
||||
</points>
|
||||
<bodyColor hex="ffe303"/>
|
||||
<borderColor hex="b29e02"/>
|
||||
<labelColor hex="000000"/>
|
||||
<leadColor hex="cccccc"/>
|
||||
<display>VALUE</display>
|
||||
<flipStanding>false</flipStanding>
|
||||
<labelOriantation>Directional</labelOriantation>
|
||||
<moveLabel>false</moveLabel>
|
||||
<hideShortLeads>false</hideShortLeads>
|
||||
<value value="1.2" unit="nF"/>
|
||||
<voltage>_63V</voltage>
|
||||
<showOuterFoil>false</showOuterFoil>
|
||||
<outerFoilColor hex="ffffff"/>
|
||||
</diylc.passive.AxialFilmCapacitor>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W5</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.2" y="4.1"/>
|
||||
<point x="2.4" y="4.2"/>
|
||||
<point x="2.6" y="4.0"/>
|
||||
<point x="2.9" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="666666"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W5</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.2" y="4.1"/>
|
||||
<point x="2.3" y="4.2"/>
|
||||
<point x="2.3" y="4.4"/>
|
||||
<point x="2.2" y="4.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.misc.Label>
|
||||
<name>L1</name>
|
||||
<point x="3.3" y="4.1"/>
|
||||
<text>To bridge baseplate</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L2</name>
|
||||
<point x="1.5" y="4.8"/>
|
||||
<text>Treble bleed</text>
|
||||
<font reference="../../diylc.misc.Label/font"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L3</name>
|
||||
<point x="2.0" y="0.2"/>
|
||||
<text>Travelcaster Wiring Diagram</text>
|
||||
<font name="Dialog" size="36" style="0"/>
|
||||
<color hex="0000cc"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L3</name>
|
||||
<point x="2.0" y="0.3"/>
|
||||
<text>www.diy-fever.com</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L4</name>
|
||||
<point x="1.9" y="1.1"/>
|
||||
<text>Pickup selector switch</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L4</name>
|
||||
<point x="2.0" y="3.2"/>
|
||||
<text>Split mode</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L4</name>
|
||||
<point x="2.0" y="3.3"/>
|
||||
<text>Push-pull</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L5</name>
|
||||
<point x="0.4" y="3.1"/>
|
||||
<text>DiMarzio</text>
|
||||
<font name="Dialog" size="18" style="1"/>
|
||||
<color hex="ffffff"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>_270</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L5</name>
|
||||
<point x="3.4" y="1.4"/>
|
||||
<text>DiMarzio</text>
|
||||
<font name="Dialog" size="18" style="1"/>
|
||||
<color hex="ffffff"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>_90</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L6</name>
|
||||
<point x="0.1" y="5.4"/>
|
||||
<text>* One of the pickups is rotated 180 degrees for cleaner drawing</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>LEFT</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L1</name>
|
||||
<point x="3.6" y="4.5"/>
|
||||
<text>Output jack</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
</components>
|
||||
<groups/>
|
||||
<lockedLayers/>
|
||||
<lockedComponents/>
|
||||
<hiddenLayers/>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
</project>
|
||||
@@ -0,0 +1,574 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<project>
|
||||
<fileVersion>
|
||||
<major>5</major>
|
||||
<minor>5</minor>
|
||||
<build>0</build>
|
||||
</fileVersion>
|
||||
<title>New Project</title>
|
||||
<author>bancika</author>
|
||||
<width value="10.0" unit="cm"/>
|
||||
<height value="14.0" unit="cm"/>
|
||||
<gridSpacing value="0.1" unit="in"/>
|
||||
<dotSpacing>1</dotSpacing>
|
||||
<components>
|
||||
<diylc.passive.PotentiometerPanel>
|
||||
<name>Volume</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints>
|
||||
<point x="1.8" y="4.5"/>
|
||||
<point x="2.0" y="4.5"/>
|
||||
<point x="2.2" y="4.5"/>
|
||||
</controlPoints>
|
||||
<resistance value="250.0" unit="K"/>
|
||||
<orientation>DEFAULT</orientation>
|
||||
<taper>LOG</taper>
|
||||
<bodyDiameter value="16.0" unit="mm"/>
|
||||
<spacing value="0.2" unit="in"/>
|
||||
<lugDiameter value="0.15" unit="in"/>
|
||||
<bodyColor hex="b6b6b6"/>
|
||||
<borderColor hex="808080"/>
|
||||
<nutColor hex="cbd5db"/>
|
||||
<waferColor hex="cd8500"/>
|
||||
<type>ThroughHole</type>
|
||||
<showShaft>false</showShaft>
|
||||
<view>ShaftDown</view>
|
||||
</diylc.passive.PotentiometerPanel>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W7</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="1.9" y="2.5"/>
|
||||
<point x="1.5" y="3.6"/>
|
||||
<point x="1.0" y="3.9"/>
|
||||
<point x="1.8" y="4.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="cc00cc"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.guitar.SingleCoilPickup>
|
||||
<name>Neck</name>
|
||||
<alpha>127</alpha>
|
||||
<value>Chopper</value>
|
||||
<orientation>_90</orientation>
|
||||
<controlPoint x="3.0" y="2.4"/>
|
||||
<controlPoints>
|
||||
<point x="3.0" y="2.4"/>
|
||||
<point x="3.0" y="2.3"/>
|
||||
<point x="3.0" y="2.2"/>
|
||||
<point x="3.0" y="2.1"/>
|
||||
</controlPoints>
|
||||
<polarity>Humbucking</polarity>
|
||||
<labelColor hex="ffffff"/>
|
||||
<color hex="666666"/>
|
||||
<poleColor hex="333333"/>
|
||||
<baseColor hex="666666"/>
|
||||
<type>Stratocaster</type>
|
||||
<polePieceType>RailHumbucker</polePieceType>
|
||||
<lugColor hex="e0c04c"/>
|
||||
</diylc.guitar.SingleCoilPickup>
|
||||
<diylc.guitar.SingleCoilPickup>
|
||||
<name>Bridge</name>
|
||||
<alpha>127</alpha>
|
||||
<value></value>
|
||||
<orientation>_270</orientation>
|
||||
<controlPoint x="0.8" y="2.1"/>
|
||||
<controlPoints>
|
||||
<point x="0.8" y="2.1"/>
|
||||
<point x="0.8" y="2.2"/>
|
||||
<point x="0.8" y="2.3"/>
|
||||
<point x="0.8" y="2.4"/>
|
||||
</controlPoints>
|
||||
<polarity>Humbucking</polarity>
|
||||
<labelColor hex="ffffff"/>
|
||||
<color hex="666666"/>
|
||||
<poleColor hex="333333"/>
|
||||
<baseColor hex="666666"/>
|
||||
<type>Stratocaster</type>
|
||||
<polePieceType>RailHumbucker</polePieceType>
|
||||
<lugColor hex="e0c04c"/>
|
||||
</diylc.guitar.SingleCoilPickup>
|
||||
<diylc.guitar.LPSwitch>
|
||||
<name>SW1</name>
|
||||
<alpha>127</alpha>
|
||||
<value></value>
|
||||
<controlPoints>
|
||||
<point x="1.9" y="1.2"/>
|
||||
<point x="1.7" y="2.495"/>
|
||||
<point x="1.9" y="2.495"/>
|
||||
<point x="2.1" y="2.495"/>
|
||||
</controlPoints>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.guitar.LPSwitch>
|
||||
<diylc.electromechanical.MiniToggleSwitch>
|
||||
<name defined-in="diylc.AbstractComponent">Split</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints>
|
||||
<point x="1.9" y="3.5"/>
|
||||
<point x="1.9" y="3.7"/>
|
||||
<point x="1.9" y="3.9"/>
|
||||
<point x="2.1" y="3.5"/>
|
||||
<point x="2.1" y="3.7"/>
|
||||
<point x="2.1" y="3.9"/>
|
||||
</controlPoints>
|
||||
<switchType>DPDT</switchType>
|
||||
<orientation>VERTICAL</orientation>
|
||||
<spacing value="0.2" unit="in"/>
|
||||
<bodyColor hex="3299cc"/>
|
||||
<borderColor hex="236b8e"/>
|
||||
<terminalPadColor hex="287ba4"/>
|
||||
<terminalColor hex="eeeeee"/>
|
||||
<showMarkers>false</showMarkers>
|
||||
</diylc.electromechanical.MiniToggleSwitch>
|
||||
<diylc.electromechanical.OpenJack1__4>
|
||||
<name>J1</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints>
|
||||
<point x="2.7" y="4.9"/>
|
||||
<point x="2.9" y="4.5"/>
|
||||
<point x="3.6" y="4.6"/>
|
||||
</controlPoints>
|
||||
<orientation>_270</orientation>
|
||||
<angle>270</angle>
|
||||
<type>MONO</type>
|
||||
<showLabels>true</showLabels>
|
||||
</diylc.electromechanical.OpenJack1__4>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W2</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.3"/>
|
||||
<point x="1.2" y="2.6"/>
|
||||
<point x="1.7" y="3.4"/>
|
||||
<point x="1.9" y="3.7"/>
|
||||
</controlPoints2>
|
||||
<color hex="ffffff"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W2</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.2"/>
|
||||
<point x="1.5" y="2.6"/>
|
||||
<point x="1.7" y="3.5"/>
|
||||
<point x="1.9" y="3.7"/>
|
||||
</controlPoints2>
|
||||
<color hex="666666"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.4"/>
|
||||
<point x="1.0" y="4.1"/>
|
||||
<point x="2.1" y="4.6"/>
|
||||
<point x="2.2" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="3.0" y="2.3"/>
|
||||
<point x="2.4" y="3.0"/>
|
||||
<point x="2.8" y="4.0"/>
|
||||
<point x="2.2" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="666666"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W4</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="0.8" y="2.1"/>
|
||||
<point x="1.1" y="2.3"/>
|
||||
<point x="1.4" y="2.7"/>
|
||||
<point x="1.7" y="2.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="ff0000"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.2" y="4.1"/>
|
||||
<point x="2.7" y="4.2"/>
|
||||
<point x="2.3" y="4.6"/>
|
||||
<point x="2.9" y="4.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.0" y="4.5"/>
|
||||
<point x="2.3" y="4.7"/>
|
||||
<point x="2.3" y="5.1"/>
|
||||
<point x="2.7" y="4.9"/>
|
||||
</controlPoints2>
|
||||
<color hex="ff0000"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W5</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.1" y="3.9"/>
|
||||
<point x="2.2" y="3.9"/>
|
||||
<point x="2.3" y="4.0"/>
|
||||
<point x="2.2" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W6</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="1.9" y="3.9"/>
|
||||
<point x="1.9" y="3.8"/>
|
||||
<point x="2.1" y="3.8"/>
|
||||
<point x="2.1" y="3.9"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W3</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="3.0" y="2.2"/>
|
||||
<point x="2.6" y="2.6"/>
|
||||
<point x="2.1" y="2.6"/>
|
||||
<point x="2.1" y="2.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="ffffff"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W4</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.1" y="3.7"/>
|
||||
<point x="2.2" y="3.5"/>
|
||||
<point x="2.5" y="3.2"/>
|
||||
<point x="3.0" y="2.4"/>
|
||||
</controlPoints2>
|
||||
<color hex="ff0000"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W6</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.1" y="3.7"/>
|
||||
<point x="2.3" y="3.5"/>
|
||||
<point x="2.7" y="2.1"/>
|
||||
<point x="3.0" y="2.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.passive.AxialFilmCapacitor>
|
||||
<name>Cbleed</name>
|
||||
<alpha>127</alpha>
|
||||
<length value="0.4" unit="in"/>
|
||||
<width value="0.125" unit="in"/>
|
||||
<points>
|
||||
<point x="1.8" y="5.1"/>
|
||||
<point x="1.8" y="4.5"/>
|
||||
<point x="1.8" y="4.8"/>
|
||||
</points>
|
||||
<bodyColor hex="ffe303"/>
|
||||
<borderColor hex="b29e02"/>
|
||||
<labelColor hex="000000"/>
|
||||
<leadColor hex="cccccc"/>
|
||||
<display>VALUE</display>
|
||||
<flipStanding>false</flipStanding>
|
||||
<labelOriantation>Directional</labelOriantation>
|
||||
<moveLabel>false</moveLabel>
|
||||
<value value="1.2" unit="nF"/>
|
||||
<voltage>_63V</voltage>
|
||||
<showOuterFoil>false</showOuterFoil>
|
||||
<outerFoilColor hex="ffffff"/>
|
||||
</diylc.passive.AxialFilmCapacitor>
|
||||
<diylc.passive.Resistor>
|
||||
<name>Rbleed</name>
|
||||
<alpha>127</alpha>
|
||||
<length value="0.4" unit="in"/>
|
||||
<width value="0.1" unit="in"/>
|
||||
<points>
|
||||
<point x="2.0" y="4.5"/>
|
||||
<point x="2.0" y="5.1"/>
|
||||
<point x="2.0" y="4.8"/>
|
||||
</points>
|
||||
<bodyColor hex="82cffd"/>
|
||||
<borderColor hex="5b90b1"/>
|
||||
<labelColor hex="000000"/>
|
||||
<leadColor hex="cccccc"/>
|
||||
<display>VALUE</display>
|
||||
<flipStanding>false</flipStanding>
|
||||
<labelOriantation>Directional</labelOriantation>
|
||||
<moveLabel>false</moveLabel>
|
||||
<value value="130.0" unit="K"/>
|
||||
<power>HALF</power>
|
||||
<colorCode>_5_BAND</colorCode>
|
||||
<shape>Standard</shape>
|
||||
</diylc.passive.Resistor>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W8</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="1.8" y="5.1"/>
|
||||
<point x="1.8" y="5.2"/>
|
||||
<point x="2.0" y="5.2"/>
|
||||
<point x="2.0" y="5.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="cccccc"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_26</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W5</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.2" y="4.1"/>
|
||||
<point x="2.4" y="4.2"/>
|
||||
<point x="2.6" y="4.0"/>
|
||||
<point x="2.9" y="4.1"/>
|
||||
</controlPoints2>
|
||||
<color hex="666666"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.connectivity.HookupWire>
|
||||
<name>W5</name>
|
||||
<alpha>127</alpha>
|
||||
<controlPoints2>
|
||||
<point x="2.2" y="4.1"/>
|
||||
<point x="2.3" y="4.2"/>
|
||||
<point x="2.3" y="4.4"/>
|
||||
<point x="2.2" y="4.5"/>
|
||||
</controlPoints2>
|
||||
<color hex="00ff00"/>
|
||||
<pointCount>FOUR</pointCount>
|
||||
<style>SOLID</style>
|
||||
<smooth>true</smooth>
|
||||
<lastUpdatePointIndex>-1</lastUpdatePointIndex>
|
||||
<gauge>_22</gauge>
|
||||
<striped>false</striped>
|
||||
<stripeColor hex="ffff00"/>
|
||||
</diylc.connectivity.HookupWire>
|
||||
<diylc.misc.Label>
|
||||
<name>L1</name>
|
||||
<point x="3.3" y="4.1"/>
|
||||
<text>To bridge baseplate</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L2</name>
|
||||
<point x="1.5" y="4.8"/>
|
||||
<text>Treble bleed</text>
|
||||
<font reference="../../diylc.misc.Label/font"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L3</name>
|
||||
<point x="2.0" y="0.2"/>
|
||||
<text>Travelcaster Wiring Diagram</text>
|
||||
<font name="Dialog" size="36" style="0"/>
|
||||
<color hex="0000cc"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L3</name>
|
||||
<point x="2.0" y="0.3"/>
|
||||
<text>www.diy-fever.com</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L4</name>
|
||||
<point x="1.9" y="1.1"/>
|
||||
<text>Pickup selector switch</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L4</name>
|
||||
<point x="2.0" y="3.2"/>
|
||||
<text>Split mode</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L4</name>
|
||||
<point x="2.0" y="3.3"/>
|
||||
<text>Push-pull</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L5</name>
|
||||
<point x="0.4" y="3.1"/>
|
||||
<text>DiMarzio</text>
|
||||
<font name="Dialog" size="18" style="1"/>
|
||||
<color hex="ffffff"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>_270</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L5</name>
|
||||
<point x="3.4" y="1.4"/>
|
||||
<text>DiMarzio</text>
|
||||
<font name="Dialog" size="18" style="1"/>
|
||||
<color hex="ffffff"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>_90</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L6</name>
|
||||
<point x="0.1" y="5.4"/>
|
||||
<text>* One of the pickups is rotated 180 degrees for cleaner drawing</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>LEFT</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
<diylc.misc.Label>
|
||||
<name>L1</name>
|
||||
<point x="3.6" y="4.5"/>
|
||||
<text>Output jack</text>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
<color hex="000000"/>
|
||||
<horizontalAlignment>CENTER</horizontalAlignment>
|
||||
<verticalAlignment>CENTER</verticalAlignment>
|
||||
<orientation>DEFAULT</orientation>
|
||||
</diylc.misc.Label>
|
||||
</components>
|
||||
<groups/>
|
||||
<lockedLayers/>
|
||||
<lockedComponents/>
|
||||
<hiddenLayers/>
|
||||
<font name="Tahoma" size="14" style="0"/>
|
||||
</project>
|
||||
@@ -1,177 +0,0 @@
|
||||
---
|
||||
name: add-component
|
||||
description: Add a new component type to the DIYLC library, or substantially modify an existing one. Use when asked to create a new part (resistor variant, board, jack, switch, pickup, symbol, shape), add editable properties to a component, change how a component draws or reports connectivity, or make a component rotatable/mirrorable.
|
||||
---
|
||||
|
||||
# Adding a component to DIYLC
|
||||
|
||||
Components live in `diylc-library/src/main/java/org/diylc/components/`. They are discovered at
|
||||
runtime by Reflections scanning `org.diylc` — **there is no registry to update**. A class becomes a
|
||||
component by carrying `@ComponentDescriptor` and implementing `IDIYComponent` (in practice, by
|
||||
extending one of the abstract bases).
|
||||
|
||||
## Before writing anything
|
||||
|
||||
1. **Find the closest existing component and read it end to end.** A new axial part follows
|
||||
`passive/Resistor.java`; a new board follows `boards/VeroBoard.java`; a new schematic symbol
|
||||
follows `AbstractSchematicLeadedSymbol` subclasses; a new jack follows `electromechanical/`.
|
||||
The new class should read like a sibling of that file.
|
||||
2. **Ask whether it is really a new class.** If the request is a revision or size variant of
|
||||
something that already exists, prefer adding a `Version` (or similar enum) property to the
|
||||
existing class over creating a parallel class. That keeps old project files loading and keeps the
|
||||
toolbox from sprawling.
|
||||
3. **Pick the right package** — `passive`, `semiconductors`, `electromechanical`, `boards`, `guitar`,
|
||||
`tube`, `chassis`, `shapes`, `smd`, `connectivity`, `misc`, `autocreate`. The package should match
|
||||
the `category` in the descriptor.
|
||||
|
||||
## Choosing a base class
|
||||
|
||||
| Base | Use for |
|
||||
| --- | --- |
|
||||
| `AbstractComponent<T>` | Anything that fits nothing else |
|
||||
| `AbstractLabeledComponent<T>` | Adds name/value label rendering |
|
||||
| `AbstractTransparentComponent<T>` | Anything with an alpha/transparency property |
|
||||
| `AbstractLeadedComponent<T>` | Two-lead axial parts drawn between two points; implement `getDefaultLength()`, `getDefaultWidth()`, `getBodyShape()` |
|
||||
| `AbstractRadialComponent<T>` | Radial (two leads out the same side) parts |
|
||||
| `AbstractCurvedComponent<T>` | Curves and traces defined by control points |
|
||||
| `AbstractAngledComponent<T>` | Parts placed by point and angle |
|
||||
| `AbstractBoard` / `AbstractProtoBoard` / `AbstractVeroBoard` | Boards |
|
||||
| `AbstractMultiPartComponent<T>` | Components made of several independently drawn sections |
|
||||
| `Abstract3LegSymbol`, `AbstractDiodeSymbol`, `AbstractTubeSymbol`, `AbstractGuitarPickup`, `AbstractShape` | The obvious specialisations |
|
||||
|
||||
Extend the most specific base that fits. Do not reimplement behaviour a base already provides.
|
||||
|
||||
## The class
|
||||
|
||||
```java
|
||||
/* ... GPL header copied verbatim from HEADER.txt ... */
|
||||
package org.diylc.components.passive;
|
||||
|
||||
import ... // java.*, then third-party, then org.diylc.*
|
||||
|
||||
@ComponentDescriptor(name = "My Part", author = "Branislav Stojkovic", category = "Passive",
|
||||
creationMethod = CreationMethod.POINT_BY_POINT, instanceNamePrefix = "X",
|
||||
description = "Short sentence shown in the toolbox tooltip", zOrder = IDIYComponent.COMPONENT,
|
||||
transformer = SimpleComponentTransformer.class, enableCache = true)
|
||||
public class MyPart extends AbstractLeadedComponent<Resistance> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static Size DEFAULT_WIDTH = new Size(1d / 2, SizeUnit.in);
|
||||
public static Color BODY_COLOR = Color.decode("#82CFFD");
|
||||
|
||||
private Resistance value = null;
|
||||
|
||||
public MyPart() {
|
||||
super();
|
||||
this.bodyColor = BODY_COLOR;
|
||||
}
|
||||
|
||||
@EditableProperty(validatorClass = PositiveMeasureValidator.class)
|
||||
public Resistance getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Resistance value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, int width, int height) { ... }
|
||||
|
||||
public enum Version { // nested types last, just before the closing brace
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Requirements the framework enforces:
|
||||
|
||||
- **No-argument public constructor**, and the class must be serializable with a
|
||||
`private static final long serialVersionUID = 1L;`.
|
||||
- `@ComponentDescriptor` needs `name`, `description`, `category`, `author`, `instanceNamePrefix` and
|
||||
`zOrder` at minimum. Set `enableCache = true` for anything whose drawing is expensive and does not
|
||||
depend on neighbouring components.
|
||||
- Appearance constants are `public static` and deliberately **not final**, so they can be overridden
|
||||
at runtime. Follow that.
|
||||
- Nested types — a `Version` enum, a package or size enum, a small helper class — go at the **bottom
|
||||
of the file**, after every method, so the outer class reads top to bottom without a block of enum
|
||||
declarations in the middle of it.
|
||||
|
||||
## Editable properties
|
||||
|
||||
- Annotate the **getter** with `@EditableProperty`; a matching `setXYZ` must exist. The property name
|
||||
comes from the getter unless you pass `name`.
|
||||
- Use `sortOrder` when the order in the editor matters, `defaultable = false` for properties that
|
||||
must not be remembered as a user default, and `validatorClass` (e.g.
|
||||
`PositiveMeasureValidator`, `PositiveNonZeroMeasureValidator`) where a raw value would be invalid.
|
||||
- Use the measure types from `org.diylc.core.measures` (`Size`, `Resistance`, `Capacitance`,
|
||||
`Voltage`, `Power`, `Percentage`) rather than raw numbers — they carry units and format themselves.
|
||||
- For a runtime-computed list of allowed values, add `@DynamicList(availableValueFunction = "getXyz")`
|
||||
alongside `@EditableProperty`. (The `additionalOptions` example in `EditableProperty`'s own Javadoc
|
||||
is stale — that attribute no longer exists.)
|
||||
- Override `getValueForDisplay()` when the canvas label should combine several properties.
|
||||
|
||||
## Drawing
|
||||
|
||||
`draw(Graphics2D, ComponentState, boolean outlineMode, Project, IDrawingObserver)` runs on every
|
||||
repaint, for every instance. Treat it as a hot path.
|
||||
|
||||
- Fetch strokes from `ObjectCache.getInstance().fetchBasicStroke(w)`, `fetchZoomableStroke(w)` or
|
||||
`fetchStroke(w, dash, phase, cap)`. Do not allocate `new BasicStroke(...)` in `draw()`.
|
||||
- Honour `outlineMode` and every `ComponentState` (`NORMAL`, `SELECTED`, `DRAGGING`) the way the
|
||||
neighbouring components do.
|
||||
- `drawIcon(g2d, width, height)` is a separate, hand-drawn miniature for the toolbox — it is not a
|
||||
scaled call into `draw()`.
|
||||
|
||||
### Connectivity
|
||||
|
||||
If the component conducts, wrap the conductive drawing in
|
||||
`drawingObserver.startTrackingContinuityArea(true)` / `stopTrackingContinuityArea()`, exactly as the
|
||||
comparable component does. Getting this wrong silently corrupts continuity checks and the netlist
|
||||
without any visible rendering difference. `startTracking()` / `stopTracking()` control whether
|
||||
drawing contributes to the component's clickable area.
|
||||
|
||||
Also implement, where relevant:
|
||||
|
||||
- `getControlPointCount()`, `getControlPoint(int)`, `setControlPoint(Point2D, int)`,
|
||||
`isControlPointSticky(int)`, `getControlPointNodeName(int)` — the connection points.
|
||||
- `getInternalLinkName(int, int)` and `getSectionNames(int)` — internal conduction between points,
|
||||
needed by the netlist and analyzers.
|
||||
- `IGerberComponentSimple` or `IGerberComponentCustom` if the part should appear in Gerber output.
|
||||
|
||||
## Rotation and mirroring
|
||||
|
||||
These live in an `IComponentTransformer` under
|
||||
`diylc-library/src/main/java/org/diylc/components/transform/`, referenced from the `transformer`
|
||||
attribute of `@ComponentDescriptor` — never inside the component itself. Reuse
|
||||
`SimpleComponentTransformer` or an existing transformer where the behaviour matches; write a new one
|
||||
only when the part rotates or mirrors differently from everything that exists.
|
||||
|
||||
## Datasheets and variants
|
||||
|
||||
If the part has a catalogue of real-world values and sizes, set `enableDatasheet = true` and
|
||||
`datasheetCreationStepCount`, and add the file under
|
||||
`diylc-library/src/main/resources/datasheets/`. Follow the format of an existing `.datasheet` file
|
||||
and add a spot-check to `DatasheetServiceTest`.
|
||||
|
||||
## Backward compatibility
|
||||
|
||||
Once a component ships, its serialized shape is a contract:
|
||||
|
||||
- Never rename, remove, or retype a serialized field, and never rename or move the class.
|
||||
- To replace a property, keep the old field, mark the old accessors `@Deprecated`, add the new field,
|
||||
and migrate lazily in the new getter — see `AbstractTransparentComponent.getAlpha()`,
|
||||
`Resistor.getPowerNew()`, `AbstractFilmCapacitor.getVoltageNew()`.
|
||||
- Fields added later arrive as `null` from old files; default them in the getter, not the
|
||||
constructor.
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
mvn -q -pl diylc-library -am test
|
||||
```
|
||||
|
||||
Then state plainly that the component still needs a visual check in the running app — automated tests
|
||||
do not cover component appearance. Offer a regression-suite run (see the `regression-test` skill) for
|
||||
any change to an existing component's drawing or serialization.
|
||||
@@ -1,129 +0,0 @@
|
||||
---
|
||||
name: add-plugin
|
||||
description: Add or modify a DIYLC Swing plugin, menu action, toolbar item, dialog or side panel. Use when asked to add a UI feature, a menu entry, a new tool window, a background task, or to react to domain events like selection or project changes.
|
||||
---
|
||||
|
||||
# Adding a plugin or UI feature to DIYLC
|
||||
|
||||
The Swing module is a shell that hosts plugins. Everything the user sees — the toolbox, the canvas,
|
||||
every menu, the status bar, autosave — is an `IPlugIn`. Adding UI means adding or extending a plugin,
|
||||
not reaching into frames.
|
||||
|
||||
## Where things go
|
||||
|
||||
| Path | Contents |
|
||||
| --- | --- |
|
||||
| `diylc-swing/src/main/java/org/diylc/swing/plugins/<name>/` | One package per plugin |
|
||||
| `diylc-swing/src/main/java/org/diylc/swing/actions/` | `AbstractAction` implementations, grouped into `file`, `edit`, `analyze` sub-packages |
|
||||
| `diylc-swing/src/main/java/org/diylc/swing/gui/` | `MainFrame`, dialogs, editors, shared components |
|
||||
| `diylc-swing/src/main/java/org/diylc/swing/gui/MainFrame.java` | Where plugins are installed |
|
||||
|
||||
## Before writing anything
|
||||
|
||||
Read the plugin closest to what is being asked. `plugins/autosave/AutoSavePlugin.java` is the
|
||||
smallest complete example (event subscription plus background work);
|
||||
`plugins/statusbar/`, `plugins/layers/` and `plugins/analyze/` show menu and panel injection.
|
||||
Match the one you read.
|
||||
|
||||
## The plugin
|
||||
|
||||
```java
|
||||
/* ... GPL header from HEADER.txt ... */
|
||||
package org.diylc.swing.plugins.myfeature;
|
||||
|
||||
public class MyFeaturePlugin implements IPlugIn {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(MyFeaturePlugin.class);
|
||||
|
||||
private ISwingUI swingUI;
|
||||
private IPlugInPort plugInPort;
|
||||
|
||||
public MyFeaturePlugin(ISwingUI swingUI) {
|
||||
this.swingUI = swingUI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(IPlugInPort plugInPort) {
|
||||
this.plugInPort = plugInPort;
|
||||
swingUI.injectMenuAction(new MyAction(plugInPort), "Tools");
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumSet<EventType> getSubscribedEventTypes() {
|
||||
return EnumSet.of(EventType.SELECTION_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(EventType eventType, Object... params) {
|
||||
if (eventType == EventType.SELECTION_CHANGED) {
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Install it in `MainFrame` alongside the others:
|
||||
|
||||
```java
|
||||
presenter.installPlugin(() -> new MyFeaturePlugin(this));
|
||||
```
|
||||
|
||||
Order matters for menus and for docked panels — insert the line where the resulting menu or panel
|
||||
position is correct, not blindly at the end.
|
||||
|
||||
## Talking to the domain
|
||||
|
||||
Plugins reach the domain **only** through `IPlugInPort`. Never import a concrete component type into
|
||||
a plugin unless the feature is genuinely component-specific, and never call into `Presenter`
|
||||
directly. If `IPlugInPort` lacks what you need, adding a method there is the right move — but it also
|
||||
means touching `diylc-core`, so keep the addition minimal and in the style of its neighbours.
|
||||
|
||||
## Reacting to events
|
||||
|
||||
`getSubscribedEventTypes()` returns an `EnumSet<EventType>`. Subscribe to the narrowest set that
|
||||
works. `PROJECT_MODIFIED`, `REPAINT` and `MOUSE_MOVED` fire constantly — anything non-trivial in
|
||||
response to those will be felt as lag. The available types are in
|
||||
`diylc-core/src/main/java/org/diylc/common/EventType.java` (`PROJECT_LOADED`, `PROJECT_SAVED`,
|
||||
`SELECTION_CHANGED`, `ZOOM_CHANGED`, `SLOT_CHANGED`, `LAYER_STATE_CHANGED`, `CLOUD_LOGGED_IN`, …).
|
||||
|
||||
## Injecting UI
|
||||
|
||||
- `swingUI.injectMenuAction(action, "Menu Name")` — a menu item; passing a `null` action inserts a
|
||||
separator, and a missing menu is created automatically.
|
||||
- `swingUI.injectSubmenu(name, icon, parentMenuName)` and
|
||||
`injectDynamicSubmenu(name, icon, parentMenuName, handler)` for submenus.
|
||||
- `swingUI.injectGUIComponent(component, SwingConstants.LEFT, collapsible, visibilityConfigKey)` for
|
||||
a docked panel. `TOP`, `BOTTOM`, `LEFT`, `RIGHT` are valid; `CENTER` is reserved for the canvas.
|
||||
Pass a config key for collapsible panels so the open/closed state persists.
|
||||
- `swingUI.getOwnerFrame()` is the parent for dialogs.
|
||||
|
||||
## Actions
|
||||
|
||||
Actions are small classes extending `javax.swing.AbstractAction`, holding an `IPlugInPort`, setting
|
||||
their label with `putValue(AbstractAction.NAME, ...)`, and delegating to `plugInPort` in
|
||||
`actionPerformed`. See `actions/RenumberAction.java` for the minimal shape. They carry
|
||||
`private static final long serialVersionUID = 1L;` like any Swing class.
|
||||
|
||||
## Background work
|
||||
|
||||
Never block the EDT. Use `swingUI.executeBackgroundTask(task, blockUI)` with an `ITask<T>`, which
|
||||
handles the busy cursor and optional glass pane, or a dedicated executor for periodic work as
|
||||
`AutoSavePlugin` does.
|
||||
|
||||
## Settings and strings
|
||||
|
||||
- Persisted preferences: `ConfigurationManager.getInstance().readString(KEY, default)` and
|
||||
`writeValue(KEY, value)`, with the key as a `String` constant. Implement `IConfigListener` to react
|
||||
to changes.
|
||||
- Every user-visible string goes through `LangUtil.translate("...")`.
|
||||
- Icons come from `IconLoader`.
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
mvn -q -pl diylc-swing -am compile
|
||||
```
|
||||
|
||||
Compilation is not evidence that the UI works. Say so, and offer to walk through launching the app
|
||||
via `.run/DIYLCStarter.run.xml` (which carries the required `--add-opens` / `--add-exports` flags) for
|
||||
a visual check.
|
||||
@@ -1,84 +0,0 @@
|
||||
---
|
||||
name: regression-test
|
||||
description: Run the DIYLC end-to-end regression suite, which renders ~700 sample .diy projects and compares PNG exports and netlists against reference outputs. Use after any change to rendering, component drawing, serialization, netlist or analyzer logic, or when asked to check for regressions or regenerate reference files.
|
||||
---
|
||||
|
||||
# Running the DIYLC regression suite
|
||||
|
||||
`RegressionTestRunner` (in `diylc-swing/src/test/java/org/diylc/`) loads every sample project under
|
||||
`diylc-regression-data/input`, exports a PNG and extracts netlists, and compares both against
|
||||
reference files produced by a known-good build. It is the only automated coverage of component
|
||||
appearance and of the file format end to end — unit tests do not touch either.
|
||||
|
||||
**Always ask before running the full suite**, and never run `PREPARE` without explicit instruction.
|
||||
|
||||
## Modes
|
||||
|
||||
- **`TEST`** — compares against the reference files and writes a CSV report plus visual diff images.
|
||||
This is what you almost always want.
|
||||
- **`PREPARE`** — *regenerates* the reference PNGs and netlists from the current build. This
|
||||
overwrites the golden copy and is correct only once a human has inspected the differences and
|
||||
decided they are intended. Never run it on your own initiative.
|
||||
|
||||
## Easiest path
|
||||
|
||||
If the maintainer is at their IDE, the `.run/RegressionTestRunner.run.xml` IntelliJ configuration
|
||||
already has the arguments and JVM flags. Offer that first.
|
||||
|
||||
## From the terminal
|
||||
|
||||
The runner needs the `--add-opens` / `--add-exports` flags and a classpath spanning all three
|
||||
modules; `mvn exec:java` will not work because it runs in Maven's own classloader and fails to find
|
||||
Reflections. Build a classpath and fork a JVM:
|
||||
|
||||
```bash
|
||||
cd diylc
|
||||
SP=/tmp # or the session scratchpad
|
||||
|
||||
mvn -q -pl diylc-swing -am test-compile
|
||||
mvn -q -pl diylc-swing dependency:build-classpath -Dmdep.outputFile=$SP/cp-swing.txt -Dmdep.includeScope=test
|
||||
mvn -q -pl diylc-core dependency:build-classpath -Dmdep.outputFile=$SP/cp-core.txt -Dmdep.includeScope=test
|
||||
mvn -q -pl diylc-library dependency:build-classpath -Dmdep.outputFile=$SP/cp-lib.txt -Dmdep.includeScope=test
|
||||
|
||||
java \
|
||||
--add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED \
|
||||
--add-exports java.desktop/com.apple.eio=ALL-UNNAMED \
|
||||
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||
--add-opens java.base/java.lang=ALL-UNNAMED \
|
||||
--add-opens java.base/java.text=ALL-UNNAMED \
|
||||
--add-opens java.desktop/java.awt=ALL-UNNAMED \
|
||||
--add-opens java.desktop/java.awt.font=ALL-UNNAMED \
|
||||
--add-opens java.desktop/java.awt.geom=ALL-UNNAMED \
|
||||
-cp "diylc-swing/target/test-classes:diylc-swing/target/classes:diylc-core/target/classes:diylc-library/target/classes:$(cat $SP/cp-swing.txt):$(cat $SP/cp-core.txt):$(cat $SP/cp-lib.txt)" \
|
||||
org.diylc.RegressionTestRunner \
|
||||
"$(cd .. && pwd)/diylc-regression-data" TEST [filter]
|
||||
```
|
||||
|
||||
Sanity-check the log line `Presenter - Current DIYLC version: 6.4.0` near the end. If it reports
|
||||
`5.0.0`, the `--add-opens` flags are missing and the run is invalid.
|
||||
|
||||
### Arguments
|
||||
|
||||
1. Path to `diylc-regression-data`
|
||||
2. `TEST` or `PREPARE`
|
||||
3. Optional filter — a substring matched against file paths. **Use it.** The full suite is ~700
|
||||
projects; while narrowing down an issue, run one file or one directory at a time
|
||||
(e.g. `splitter2`, or `guitar`).
|
||||
|
||||
## Reading the results
|
||||
|
||||
- A CSV report is written to `diylc-regression-data/reports/`, named with the timestamp and version,
|
||||
listing each file as OK or failed with the reason (`Images do not match`, `Netlists do not match
|
||||
with switches`, `Netlists do not match without switches`).
|
||||
- Rendered output and **visual diff images**, with red rectangles around every differing region, go
|
||||
to `diylc-regression-data/output/` (not under version control).
|
||||
- Reports are kept as historical evidence. If a run was exploratory rather than a real verification,
|
||||
delete the generated CSV afterwards so the reports directory stays meaningful — and check
|
||||
`git status` before finishing, since the runner writes into the repo.
|
||||
|
||||
## Interpreting a failure
|
||||
|
||||
A difference is not automatically a bug, but it is always a change the maintainer must see. Report
|
||||
which files differ and what kind of difference it is; where an image diff exists, point at the file
|
||||
so it can be looked at. Do not conclude "no regressions" from a filtered run — say exactly which
|
||||
subset was run.
|
||||
@@ -147,10 +147,3 @@ buildNumber.properties
|
||||
|
||||
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
|
||||
!/.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################
|
||||
###### Custom ######
|
||||
######################
|
||||
|
||||
# Deployment folder
|
||||
deploy/
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="DIYLCStarter" type="Application" factoryName="Application" nameIsGenerated="true">
|
||||
<option name="ALTERNATIVE_JRE_PATH" value="temurin-21" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
|
||||
<option name="MAIN_CLASS_NAME" value="org.diylc.DIYLCStarter" />
|
||||
<module name="diylc-swing" />
|
||||
<option name="VM_PARAMETERS" value="-Xms1024m -Xmx4096m -Ddorg.diylc.debugAreaPerformance=true -Dorg.diylc.scriptRun=true -Ddorg.diylc.cloud.baseUrl=http://localhost:8080 -Dfile.encoding=UTF-8 --add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED --add-exports java.desktop/com.apple.eio=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.desktop/java.awt.geom=ALL-UNNAMED" />
|
||||
<option name="VM_PARAMETERS" value="-Xms1024m -Xmx4096m -Ddorg.diylc.debugAreaPerformance=true -Dorg.diylc.scriptRun=true -Dfile.encoding=UTF-8 --add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED --add-exports java.desktop/com.apple.eio=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.desktop/java.awt.geom=ALL-UNNAMED" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="org.diylc.*" />
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="RegressionTestRunner" type="Application" factoryName="Application" nameIsGenerated="true">
|
||||
<option name="MAIN_CLASS_NAME" value="org.diylc.RegressionTestRunner" />
|
||||
<module name="diylc-swing" />
|
||||
<option name="PROGRAM_PARAMETERS" value="$PROJECT_DIR$/../diylc-regression-data TEST" />
|
||||
<option name="VM_PARAMETERS" value="--add-exports java.desktop/com.apple.eawt.event=ALL-UNNAMED --add-exports java.desktop/com.apple.eio=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.text=ALL-UNNAMED --add-opens java.desktop/java.awt=ALL-UNNAMED --add-opens java.desktop/java.awt.font=ALL-UNNAMED --add-opens java.desktop/java.awt.geom=ALL-UNNAMED" />
|
||||
<extension name="coverage">
|
||||
<pattern>
|
||||
<option name="PATTERN" value="org.diylc.*" />
|
||||
<option name="ENABLED" value="true" />
|
||||
</pattern>
|
||||
</extension>
|
||||
<method v="2">
|
||||
<option name="Make" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1 +0,0 @@
|
||||
CLAUDE.md
|
||||
-216
@@ -1,216 +0,0 @@
|
||||
# DIY Layout Creator — agent guidelines
|
||||
|
||||
DIYLC is a Java 21 Swing desktop application for drawing circuit layouts, schematics and guitar
|
||||
wiring diagrams. It is a mature codebase (~690 source files) with long-standing conventions and a
|
||||
file format that must stay readable by every version. **Consistency with the surrounding code
|
||||
outweighs personal preference or modern idiom in every case.**
|
||||
|
||||
## The one rule that matters most
|
||||
|
||||
Before writing anything, read two or three existing files that do the same kind of job — the
|
||||
neighbouring component, the sibling plugin, the analyzer next to the one you are touching — and
|
||||
match them. Match their naming, their structure, their comment density, their ordering of members,
|
||||
their choice of helper classes. If your change looks different from its neighbours, it is wrong even
|
||||
if it compiles and works.
|
||||
|
||||
## Modules
|
||||
|
||||
Maven reactor rooted at `diylc/pom.xml`, version `6.4.0`, three modules with a strict one-way
|
||||
dependency chain:
|
||||
|
||||
| Module | Contains | Depends on |
|
||||
| --- | --- | --- |
|
||||
| `diylc-core` | Domain model, `Presenter`, rendering pipeline, messaging, serialization, netlist engine, annotations | — |
|
||||
| `diylc-library` | Concrete component classes, transformers, datasheets, legacy file parsers, component-aware analyzers | `diylc-core` |
|
||||
| `diylc-swing` | Swing shell, plugins, dialogs, editors, `DIYLCStarter` | `diylc-core`, `diylc-library` |
|
||||
|
||||
**`diylc-core` must never reference a concrete component type.** It knows components only through
|
||||
`IDIYComponent` and the annotations. If core logic seems to need knowledge of a specific component,
|
||||
that knowledge belongs in `diylc-library` (an analyzer, a transformer, a parser) or is exposed
|
||||
through a new interface in core that the component implements — look at
|
||||
`org.diylc.core.gerber.IGerberComponentSimple` for the established shape of that escape hatch.
|
||||
|
||||
Component and plugin classes are discovered at runtime by Reflections scanning the `org.diylc`
|
||||
package (`ComponentProcessor`). There is no registry to update when adding a component.
|
||||
|
||||
## Build and verify
|
||||
|
||||
Run from `diylc/`. Before reporting a change as done:
|
||||
|
||||
```bash
|
||||
mvn -q -pl diylc-core -am compile # after core changes
|
||||
mvn -q -pl diylc-library -am test # after library changes (~20s)
|
||||
mvn -q -pl diylc-swing -am compile # after swing changes
|
||||
mvn -q test # whole reactor, when the change spans modules
|
||||
```
|
||||
|
||||
Compile the module you touched plus everything downstream of it, and run the unit tests of any
|
||||
module whose tests could plausibly cover the change. Do not report success without having actually
|
||||
run these — quote the failure if something breaks rather than describing it.
|
||||
|
||||
Do not run `mvn package`, `build-all-profiles.sh`, or the regression suite unless asked; they are
|
||||
slow and the deployment build needs Docker and signing certificates. The regression suite is
|
||||
described in `.claude/skills/regression-test/SKILL.md` and is worth *offering* whenever a change
|
||||
affects rendering, serialization or netlist output.
|
||||
|
||||
The app runs from the `.run/DIYLCStarter.run.xml` IntelliJ configuration, which carries the required
|
||||
`--add-opens`/`--add-exports` JVM flags. Copy them if launching from a terminal.
|
||||
|
||||
## Code style
|
||||
|
||||
The formatter is `eclipse-java-google-style.xml` (Google Java Style):
|
||||
|
||||
- **Two-space indent**, four spaces for continuation lines. No tabs.
|
||||
- **100-column** line limit.
|
||||
- Source encoding is **ISO-8859-1** — do not introduce non-ASCII characters into `.java` files. Use
|
||||
Unicode escapes or the resource bundles instead.
|
||||
- Braces on the same line, and **always braces** — an `if`, `else`, `for` or `while` body gets a
|
||||
block even when it is a single statement. Plenty of older code omits them; do not copy that when
|
||||
you are writing new code, and add them when you are already editing the lines in question.
|
||||
- Imports: `java.*` first, then third-party, then `org.diylc.*`, separated by blank lines. No
|
||||
wildcard imports.
|
||||
- Constants are `UPPER_SNAKE_CASE`. Note that component appearance constants are deliberately
|
||||
`public static` and **not** `final` (`BODY_COLOR`, `DEFAULT_WIDTH`), so they can be overridden at
|
||||
runtime; keep that convention when adding new ones.
|
||||
- `private static final Logger LOG = Logger.getLogger(TheClass.class);` — log4j 1.2, declared first
|
||||
among the static members. Only declare one on a class that actually needs it; see *Logging* below.
|
||||
- **Nested types go at the bottom of the file**, after every field, constructor and method of the
|
||||
enclosing class, immediately before its closing brace. A version enum or a small helper class
|
||||
declared halfway down the file pushes the code a reader came for out of sight; keeping them last
|
||||
means the outer class reads top to bottom without interruption. Several nested types keep their
|
||||
relative order.
|
||||
|
||||
### Comments
|
||||
|
||||
Write comments only where the code cannot speak for itself: a non-obvious electrical or geometric
|
||||
reason, a workaround for a library bug, a compatibility constraint, a unit or coordinate-system
|
||||
assumption. Never restate the code.
|
||||
|
||||
```java
|
||||
// BAD — adds nothing
|
||||
// set the body color
|
||||
g2d.setColor(bodyColor);
|
||||
|
||||
// GOOD — explains something the reader cannot infer
|
||||
// the outer foil marking is drawn on the lead that is closer to the first control point,
|
||||
// which is the convention printed on most film capacitors
|
||||
```
|
||||
|
||||
Javadoc on public interfaces and abstract base classes in `diylc-core` is expected and should carry
|
||||
`@author`. Concrete component classes generally carry no Javadoc — do not add it just to fill space.
|
||||
|
||||
### Logging
|
||||
|
||||
Keep logging sparse, and prefer removing a log line to adding one. A logger earns its place on a
|
||||
class that has something a maintainer would want to read back: a swallowed failure, a slow or
|
||||
one-off initialisation, an external file or service that may not be there. Do not declare a `LOG`
|
||||
field that the class never uses.
|
||||
|
||||
- `LOG.error` — something went wrong that the user or a bug report may need to explain.
|
||||
- `LOG.warn` — a recoverable surprise.
|
||||
- `LOG.info` — events that happen a handful of times per session, not per action.
|
||||
- `LOG.debug` — anything finer. Assume it is switched off in the field.
|
||||
|
||||
Never log from code on a hot path: `draw`, control-point accessors, property getters, anything the
|
||||
canvas calls on every repaint or every mouse move. The cost is real and the output buries whatever
|
||||
else is in the log.
|
||||
|
||||
Do not wrap code in `try`/`catch` only so that there is something to log. If the block cannot
|
||||
actually throw, the guard and the logger both come out.
|
||||
|
||||
### License header
|
||||
|
||||
**Every new source file starts with the GPL header**, copied verbatim from `HEADER.txt` (or from any
|
||||
existing class), immediately followed by the `package` declaration with no blank line between the
|
||||
closing `*/` and `package`. This applies to Java files in all three modules, including tests.
|
||||
|
||||
## File-format backward compatibility
|
||||
|
||||
DIYLC projects are XStream-serialized object graphs. Users open decade-old `.diy` files with the
|
||||
current build, so **the serialized shape of a component class is a public contract**.
|
||||
|
||||
- Never rename or delete a serialized field, and never change its type. To replace one, keep the old
|
||||
field, add a new one, mark the old accessors `@Deprecated`, and migrate lazily inside the new
|
||||
getter. The canonical examples are `AbstractTransparentComponent.getAlpha()` (legacy `Byte alpha`
|
||||
→ `Percentage alphaPercent`) and `Resistor.getPowerNew()` / `AbstractFilmCapacitor.getVoltageNew()`.
|
||||
- Fields added to an existing class deserialize as `null` in old files. Every read path must tolerate
|
||||
that, typically by defaulting in the getter rather than the constructor.
|
||||
- Never rename or move a component class that has shipped. If a component genuinely must change
|
||||
identity, an alias has to be registered on the XStream side and the legacy parsers in
|
||||
`V1FileParser` / `V2FileParser` reviewed.
|
||||
- Prefer **a `Version` property on a single component class over a new class per revision** when a
|
||||
board or part gains a new variant. One class with a version enum keeps old files loading and keeps
|
||||
the toolbox uncluttered.
|
||||
- Any change here calls for a regression-suite run.
|
||||
|
||||
## Components
|
||||
|
||||
See `.claude/skills/add-component/SKILL.md` for the full recipe. The rules that apply to *editing*
|
||||
existing components too:
|
||||
|
||||
- Extend the most specific abstract base that fits (`AbstractLeadedComponent`,
|
||||
`AbstractRadialComponent`, `AbstractBoard`, `AbstractTransparentComponent`, …) rather than
|
||||
reimplementing shared behaviour.
|
||||
- Every editable property needs a matching getter/setter pair with `@EditableProperty` on the
|
||||
**getter**; the property name is derived from the getter unless `name` is given.
|
||||
- Drawing code must fetch strokes from `ObjectCache.getInstance().fetchBasicStroke(...)` /
|
||||
`fetchZoomableStroke(...)` / `fetchStroke(...)` rather than allocating `new BasicStroke(...)`.
|
||||
`draw()` runs on every repaint; do not allocate what can be cached or reused.
|
||||
- Conductive areas are reported to the `IDrawingObserver` via
|
||||
`startTrackingContinuityArea(true)` / `stopTrackingContinuityArea()`. Getting this wrong silently
|
||||
breaks continuity checks and the netlist, so mirror a neighbouring component exactly.
|
||||
- Rotation and mirroring live in an `IComponentTransformer` referenced from `@ComponentDescriptor`,
|
||||
never inside the component.
|
||||
- `drawIcon()` draws into a small fixed box for the toolbox; it is hand-drawn, not scaled from
|
||||
`draw()`.
|
||||
|
||||
## Plugins and Swing
|
||||
|
||||
- Everything in the UI is an `IPlugIn` installed from `MainFrame` via `presenter.installPlugin(...)`.
|
||||
- Plugins talk to the domain only through `IPlugInPort`, and react to domain changes by returning a
|
||||
narrow `EnumSet<EventType>` from `getSubscribedEventTypes()`. Subscribe to as little as possible —
|
||||
`PROJECT_MODIFIED` fires constantly.
|
||||
- UI is injected through `ISwingUI.injectMenuAction` / `injectGUIComponent` / `injectSubmenu`, not by
|
||||
reaching into frames directly.
|
||||
- Persisted settings go through `ConfigurationManager.getInstance().readString/writeValue` with a
|
||||
`String` key constant.
|
||||
- User-visible strings are wrapped in `LangUtil.translate(...)`.
|
||||
- Long-running work belongs on a background executor, never on the EDT.
|
||||
|
||||
## Testing
|
||||
|
||||
JUnit 4 under `src/test/java` in each module. Add tests where the project already tests: switching
|
||||
logic, netlist and analyzer behaviour, datasheet parsing, core utilities. Component rendering and
|
||||
user interaction are covered by the regression suite instead, not by unit tests. Test classes are
|
||||
named `*Test` or `*Tests` and carry the license header like any other file.
|
||||
|
||||
## Git
|
||||
|
||||
**Do not commit or push.** Make the change in the working tree and stop; the maintainer reviews and
|
||||
commits. If a commit is explicitly requested, commit only what was asked for, never to a remote, and
|
||||
never `git add -A` over unrelated dirty files.
|
||||
|
||||
## Out of scope unless explicitly asked
|
||||
|
||||
- `diylc-server-api/` — PHP backend that runs in an isolated environment on diy-fever.com and cannot
|
||||
be tested locally.
|
||||
- `deploy/`, `build-all-profiles.sh`, packaging and notarization.
|
||||
- `lib/` — vendored jars for dependencies not on Maven Central.
|
||||
- `diylc-regression-data/reports/` — historical evidence, append-only.
|
||||
- Bumping the project version in the POMs.
|
||||
|
||||
## Task recipes
|
||||
|
||||
Detailed, step-by-step recipes live in `.claude/skills/` and are worth reading in full before
|
||||
starting the corresponding kind of work:
|
||||
|
||||
| Skill | Covers |
|
||||
| --- | --- |
|
||||
| `add-component` | Creating or substantially changing a component in `diylc-library` |
|
||||
| `add-plugin` | Adding UI: plugins, menu actions, panels, dialogs, background tasks |
|
||||
| `regression-test` | Running the end-to-end regression suite and reading its report |
|
||||
|
||||
## Reference
|
||||
|
||||
Chapter 13 of *Mastering DIY Layout Creator* is the authoritative developer guide and covers the
|
||||
architecture, extension points and regression suite in prose.
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script to build all Maven profiles and copy zip files to deployment folder
|
||||
# Usage: ./build-all-profiles.sh [to-deploy-folder]
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
# Parse arguments
|
||||
DEPLOY_DIR="${1:-}"
|
||||
|
||||
# Configuration
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SWING_MODULE_DIR="${PROJECT_DIR}/diylc-swing"
|
||||
DEPLOY_DIR="${DEPLOY_DIR:-${PROJECT_DIR}/deploy}"
|
||||
|
||||
# Docker must be up before jpackage-based profiles can run
|
||||
ensure_docker_running() {
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "ERROR: docker is not installed or not on PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if docker info &> /dev/null; then
|
||||
echo "Docker is already running"
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Docker is not running, attempting to start it..."
|
||||
if [[ "$(uname)" == "Darwin" ]]; then
|
||||
open -a Docker
|
||||
elif command -v systemctl &> /dev/null; then
|
||||
sudo systemctl start docker
|
||||
else
|
||||
echo "ERROR: Don't know how to start Docker on this platform"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# the daemon keeps refusing connections for a while after the app itself launches
|
||||
for _ in $(seq 1 60); do
|
||||
if docker info &> /dev/null; then
|
||||
echo "Docker is running"
|
||||
return
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "ERROR: Timed out waiting for Docker to start"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# List of profiles to build
|
||||
PROFILES=(
|
||||
"universal-zip"
|
||||
"linux-appimage"
|
||||
"win64-zip"
|
||||
"win64-installer"
|
||||
"mac-x86"
|
||||
"mac-arm"
|
||||
)
|
||||
|
||||
echo "=========================================="
|
||||
echo "Building all Maven profiles"
|
||||
echo "=========================================="
|
||||
echo "Project directory: ${PROJECT_DIR}"
|
||||
echo "Swing module directory: ${SWING_MODULE_DIR}"
|
||||
echo "Deployment directory: ${DEPLOY_DIR}"
|
||||
echo "Tests: Skipped"
|
||||
echo ""
|
||||
|
||||
ensure_docker_running
|
||||
echo ""
|
||||
|
||||
# Create deployment directory if it doesn't exist
|
||||
mkdir -p "${DEPLOY_DIR}"
|
||||
|
||||
# Change to project root directory
|
||||
cd "${PROJECT_DIR}"
|
||||
|
||||
# Build each profile (clean before each one)
|
||||
TARGET_DIR="${SWING_MODULE_DIR}/target"
|
||||
TOTAL_ZIP_COUNT=0
|
||||
|
||||
for profile in "${PROFILES[@]}"; do
|
||||
echo "----------------------------------------"
|
||||
echo "Building profile: ${profile}"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# Clean and build from root, specifying the swing module and profile
|
||||
# This ensures dependencies (diylc-core, diylc-library) are built first
|
||||
mvn clean package -pl diylc-swing -am -P"${profile}" -DskipTests || {
|
||||
echo "ERROR: Failed to build profile ${profile}"
|
||||
echo "Continuing with next profile..."
|
||||
continue
|
||||
}
|
||||
|
||||
echo "✓ Profile ${profile} built successfully"
|
||||
|
||||
# Copy zip and exe files immediately after each build (before next clean)
|
||||
if [ -d "${TARGET_DIR}" ]; then
|
||||
echo "Looking for artifacts in ${TARGET_DIR}..."
|
||||
PROFILE_FILE_COUNT=0
|
||||
|
||||
# Find all zip files in target directory (excluding DIYLC-notarize.zip)
|
||||
while IFS= read -r -d '' zipfile; do
|
||||
filename=$(basename "${zipfile}")
|
||||
# Skip DIYLC-notarize.zip files
|
||||
if [[ "${filename}" != "DIYLC-notarize.zip" ]] && [ -f "${zipfile}" ]; then
|
||||
dest="${DEPLOY_DIR}/${filename}"
|
||||
|
||||
echo " → Copying: ${filename}"
|
||||
cp "${zipfile}" "${dest}"
|
||||
TOTAL_ZIP_COUNT=$((TOTAL_ZIP_COUNT + 1))
|
||||
PROFILE_FILE_COUNT=$((PROFILE_FILE_COUNT + 1))
|
||||
fi
|
||||
done < <(find "${TARGET_DIR}" -maxdepth 1 -type f -name "*.zip" -print0 2>/dev/null)
|
||||
|
||||
# Find all exe files in target directory
|
||||
while IFS= read -r -d '' exefile; do
|
||||
if [ -f "${exefile}" ]; then
|
||||
filename=$(basename "${exefile}")
|
||||
dest="${DEPLOY_DIR}/${filename}"
|
||||
|
||||
echo " → Copying: ${filename}"
|
||||
cp "${exefile}" "${dest}"
|
||||
TOTAL_ZIP_COUNT=$((TOTAL_ZIP_COUNT + 1))
|
||||
PROFILE_FILE_COUNT=$((PROFILE_FILE_COUNT + 1))
|
||||
fi
|
||||
done < <(find "${TARGET_DIR}" -maxdepth 1 -type f -name "*.exe" -print0 2>/dev/null)
|
||||
|
||||
if [ ${PROFILE_FILE_COUNT} -eq 0 ]; then
|
||||
echo " ⚠ Warning: No artifacts found for profile ${profile}"
|
||||
# List what's actually in the target directory for debugging
|
||||
echo " Debug: Files in target directory:"
|
||||
ls -la "${TARGET_DIR}"/*.{zip,exe} 2>/dev/null | head -5 || echo " (no zip/exe files found)"
|
||||
else
|
||||
echo " ✓ Copied ${PROFILE_FILE_COUNT} file(s) from ${profile}"
|
||||
fi
|
||||
else
|
||||
echo " ⚠ Warning: Target directory ${TARGET_DIR} does not exist"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo "=========================================="
|
||||
echo "Copying summary"
|
||||
echo "=========================================="
|
||||
if [ ${TOTAL_ZIP_COUNT} -eq 0 ]; then
|
||||
echo "No artifacts were copied"
|
||||
else
|
||||
echo "✓ Copied ${TOTAL_ZIP_COUNT} file(s) total to ${DEPLOY_DIR}"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo "Build and deployment complete!"
|
||||
echo "=========================================="
|
||||
echo "Deployment folder: ${DEPLOY_DIR}"
|
||||
echo "Files:"
|
||||
ls -lh "${DEPLOY_DIR}"/*.{zip,exe} 2>/dev/null || echo " (no zip/exe files found)"
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
<parent>
|
||||
<groupId>org.diylc</groupId>
|
||||
<artifactId>diylc-parent</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>5.4.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>diylc-core</artifactId>
|
||||
<!-- No need to specify version - it inherits from parent -->
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -60,7 +60,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<version>2.16.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
@@ -74,17 +74,6 @@
|
||||
<version>5.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Subclass mock maker, selected in src/test/resources/mockito-extensions. Mockito 5
|
||||
defaults to the inline maker, which attaches a Java agent to the running JVM; that
|
||||
attachment fails outright on some CI JDKs and is deprecated since Java 21. Every type
|
||||
mocked in these tests is an interface, which the subclass maker handles without an
|
||||
agent. -->
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-subclass</artifactId>
|
||||
<version>5.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Local dependencies from lib folder -->
|
||||
<dependency>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.announcements;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility methods for detecting and extracting URLs from announcements and HTML.
|
||||
*/
|
||||
public class AnnouncementUtils {
|
||||
|
||||
private static final Pattern HREF_PATTERN = Pattern.compile(
|
||||
"href=[\"']([^\"']+)[\"']", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* Extracts the first URL found in the text or HTML.
|
||||
*
|
||||
* @param html text or HTML content
|
||||
* @return first URL found, or null if none
|
||||
*/
|
||||
public static String extractFirstUrl(String html) {
|
||||
List<String> urls = extractUrls(html);
|
||||
return urls.isEmpty() ? null : urls.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts all unique URLs found in the HTML href attributes in order of appearance.
|
||||
*
|
||||
* @param html text or HTML content
|
||||
* @return list of unique URLs
|
||||
*/
|
||||
public static List<String> extractUrls(String html) {
|
||||
List<String> urls = new ArrayList<String>();
|
||||
if (html == null || html.isEmpty()) {
|
||||
return urls;
|
||||
}
|
||||
|
||||
Matcher hrefMatcher = HREF_PATTERN.matcher(html);
|
||||
while (hrefMatcher.find()) {
|
||||
String url = hrefMatcher.group(1).trim();
|
||||
url = normalizeUrl(url);
|
||||
if (!urls.contains(url)) {
|
||||
urls.add(url);
|
||||
}
|
||||
}
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the HTML contains any link.
|
||||
*
|
||||
* @param html text or HTML content
|
||||
* @return true if at least one URL is detected, false otherwise
|
||||
*/
|
||||
public static boolean containsLink(String html) {
|
||||
return extractFirstUrl(html) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a URL to ensure it has a valid protocol if starting with www.
|
||||
*/
|
||||
public static String normalizeUrl(String url) {
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = url.trim();
|
||||
if (trimmed.startsWith("www.")) {
|
||||
return "http://" + trimmed;
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.ComponentGroup;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
@@ -45,21 +44,19 @@ public class ComponentTransferable implements Transferable, Serializable {
|
||||
public static final DataFlavor listFlavor = new DataFlavor(ComponentTransferable.class, "application/diylc");
|
||||
|
||||
private List<IDIYComponent<?>> components;
|
||||
private Set<ComponentGroup> groups;
|
||||
private String name;
|
||||
private Set<Set<IDIYComponent<?>>> groups;
|
||||
|
||||
public ComponentTransferable() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ComponentTransferable(List<IDIYComponent<?>> components, String name) {
|
||||
public ComponentTransferable(List<IDIYComponent<?>> components) {
|
||||
super();
|
||||
this.components = components;
|
||||
this.name = name;
|
||||
this.groups = null;
|
||||
}
|
||||
|
||||
public ComponentTransferable(List<IDIYComponent<?>> components, Set<ComponentGroup> groups) {
|
||||
public ComponentTransferable(List<IDIYComponent<?>> components, Set<Set<IDIYComponent<?>>> groups) {
|
||||
super();
|
||||
this.components = components;
|
||||
this.groups = groups;
|
||||
@@ -87,11 +84,7 @@ public class ComponentTransferable implements Transferable, Serializable {
|
||||
return components;
|
||||
}
|
||||
|
||||
public Set<ComponentGroup> getGroups() {
|
||||
public Set<Set<IDIYComponent<?>>> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-24
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
@@ -17,11 +17,15 @@
|
||||
*/
|
||||
package org.diylc.clipboard;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.diylc.core.ComponentGroup;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class ComponentTransferableFactory {
|
||||
@@ -36,19 +40,13 @@ public class ComponentTransferableFactory {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ComponentTransferable build(Collection<IDIYComponent<?>> selectedComponents, Set<ComponentGroup> groups) {
|
||||
|
||||
public ComponentTransferable build(Collection<IDIYComponent<?>> selectedComponents, Set<Set<IDIYComponent<?>>> groups) {
|
||||
Set<IDIYComponent<?>> originalComponentSet = new HashSet<IDIYComponent<?>>(selectedComponents);
|
||||
List<IDIYComponent<?>> originalComponents = new ArrayList<IDIYComponent<?>>(selectedComponents);
|
||||
|
||||
Map<UUID, UUID> idMap = new HashMap<>();
|
||||
|
||||
List<IDIYComponent<?>> clonedComponents = originalComponents.stream(
|
||||
).map(x -> {
|
||||
try {
|
||||
IDIYComponent<?> clone = x.clone();
|
||||
clone.setId(UUID.randomUUID());
|
||||
idMap.put(x.getId(), clone.getId());
|
||||
return clone;
|
||||
return x.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
@@ -56,18 +54,22 @@ public class ComponentTransferableFactory {
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Set<ComponentGroup> clonedGroups = groups.stream()
|
||||
.map(group -> {
|
||||
Set<UUID> newIds = group.getComponentIds().stream()
|
||||
.map(idMap::get)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
// Only create group if it has at least one valid ID
|
||||
return newIds.isEmpty() ? null : new ComponentGroup(newIds, group.getName());
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
Set<Set<IDIYComponent<?>>> clonedGroups = new HashSet<Set<IDIYComponent<?>>>();
|
||||
|
||||
for (Set<IDIYComponent<?>> group : groups) {
|
||||
if (group.isEmpty())
|
||||
continue;
|
||||
|
||||
if (originalComponentSet.contains(group.iterator().next())) {
|
||||
Set<IDIYComponent<?>> clonedGroup = new HashSet<IDIYComponent<?>>();
|
||||
clonedGroups.add(clonedGroup);
|
||||
for (int i = 0; i < originalComponents.size(); i++) {
|
||||
if (group.contains(originalComponents.get(i))) {
|
||||
clonedGroup.add(clonedComponents.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new ComponentTransferable(clonedComponents, clonedGroups);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.common;
|
||||
|
||||
/**
|
||||
* The two ways a saved {@link BuildingBlock} can be placed on the canvas.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum BlockInstantiationMode {
|
||||
|
||||
/**
|
||||
* The block's components are cloned as individual, independently selectable components and
|
||||
* grouped together (the original, and only, behavior before composite mode was introduced).
|
||||
*/
|
||||
GROUP,
|
||||
|
||||
/**
|
||||
* The block's components are cloned and wrapped in a single
|
||||
* {@code org.diylc.components.composite.CompositeComponent} that behaves as one rigid
|
||||
* component with its own name, aggregating the control points of all its children.
|
||||
*/
|
||||
COMPOSITE
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
@@ -56,14 +56,14 @@ public class ComponentType implements Serializable {
|
||||
private boolean enableCache;
|
||||
private List<String[]> datasheet;
|
||||
private int datasheetCreationStepCount;
|
||||
|
||||
public ComponentType() {
|
||||
|
||||
public ComponentType() {
|
||||
}
|
||||
|
||||
public ComponentType(String name, String description, CreationMethod creationMethod, String category,
|
||||
String namePrefix, String author, Icon icon, Class<? extends IDIYComponent<?>> instanceClass, double zOrder,
|
||||
boolean flexibleZOrder, BomPolicy bomPolicy, boolean autoEdit, IComponentTransformer transformer,
|
||||
KeywordPolicy keywordPolicy, String keywordTag, boolean enableCache, List<String[]> datasheet,
|
||||
boolean flexibleZOrder, BomPolicy bomPolicy, boolean autoEdit, IComponentTransformer transformer,
|
||||
KeywordPolicy keywordPolicy, String keywordTag, boolean enableCache, List<String[]> datasheet,
|
||||
int datasheetCreationStepCount) {
|
||||
super();
|
||||
this.name = name;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -68,9 +68,5 @@ public enum DrawOption {
|
||||
/**
|
||||
* Whether locked components should be rendered as transparent or not.
|
||||
*/
|
||||
LOCKED_ALPHA,
|
||||
/**
|
||||
* When applied, all colors will be converted to blackest black or whitest white
|
||||
*/
|
||||
MONOCHROMATIC;
|
||||
LOCKED_ALPHA;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
*/
|
||||
package org.diylc.common;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.diylc.core.Project;
|
||||
@@ -54,7 +55,12 @@ public enum EventType {
|
||||
*/
|
||||
FILE_STATUS_CHANGED,
|
||||
/**
|
||||
* Called when component selection is changed. New list of components and control point map is attached as a
|
||||
* Called when selection rectangle is changed. Object of type {@link Rectangle} is the only
|
||||
* parameter and it contains the new selection rectangle.
|
||||
*/
|
||||
SELECTION_RECT_CHANGED,
|
||||
/**
|
||||
* Called when component selection is changed. New {@link ComponentSelection} is attached as a
|
||||
* parameter.
|
||||
*/
|
||||
SELECTION_CHANGED,
|
||||
@@ -112,16 +118,5 @@ public enum EventType {
|
||||
/**
|
||||
* Signals that the Cloud account is logged out.
|
||||
*/
|
||||
CLOUD_LOGGED_OUT,
|
||||
/**
|
||||
* Called when the mouse hovers over sticky control points (nodes) in tooltip mode.
|
||||
* Parameters: String text (semicolon-separated component and node names, or null), Point point.
|
||||
*/
|
||||
NODE_NAME_HOVER_TOOLTIP,
|
||||
/**
|
||||
* Called when the set of enabled component categories changes. The first parameter is a
|
||||
* <code>Set<String></code> of disabled category names. All categories not included are
|
||||
* enabled.
|
||||
*/
|
||||
COMPONENT_CATEGORIES_CHANGED;
|
||||
CLOUD_LOGGED_OUT;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -25,28 +25,13 @@ import java.io.IOException;
|
||||
|
||||
public interface IBlockProcessor {
|
||||
|
||||
public static final String BLOCKS_KEY = "buildingBlocks";
|
||||
public static final String BLOCKS_KEY = "buildingBlocks";
|
||||
public static final String DEFAULT_BLOCKS_IMPORTED_KEY = "defaultBlocksImported";
|
||||
|
||||
/**
|
||||
* Prefix that marks a string as a reference to a building block rather than a component class
|
||||
* name. Used wherever components and blocks share a single identifier list, such as keyboard
|
||||
* shortcuts ({@code COMPONENT_SHORTCUT_KEY}) and the recently used list
|
||||
* ({@link org.diylc.common.IPlugInPort#RECENT_COMPONENTS_KEY}). A block identifier looks like
|
||||
* {@code "block:My Block Name"}.
|
||||
*/
|
||||
public static final String BLOCK_PREFIX = "block:";
|
||||
|
||||
void saveSelectionAsBlock(String blockName);
|
||||
|
||||
/**
|
||||
* Loads the block in the given {@link BlockInstantiationMode}. {@link BlockInstantiationMode#COMPOSITE}
|
||||
* (a single rigid component) is the default mode used by most call sites (see design decision D10 in
|
||||
* {@code docs/plans/composite-building-blocks.md}); {@link BlockInstantiationMode#GROUP} instantiates
|
||||
* the block as a group of loose components.
|
||||
*/
|
||||
void loadBlock(String blockName, BlockInstantiationMode mode) throws InvalidBlockException;
|
||||
|
||||
void loadBlock(String blockName) throws InvalidBlockException;
|
||||
|
||||
void deleteBlock(String blockName);
|
||||
|
||||
int importBlocks(String fileName) throws IOException;
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.filter;
|
||||
package org.diylc.common;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.common;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.core.ComponentGroup;
|
||||
|
||||
/**
|
||||
* Interface for component grouping operations.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IGroupProcessor {
|
||||
|
||||
/**
|
||||
* Returns the set of component groups in the current project. Each group is a set of components
|
||||
* that are grouped together.
|
||||
*
|
||||
* @return set of component groups
|
||||
*/
|
||||
Set<ComponentGroup> getComponentGroups();
|
||||
|
||||
/**
|
||||
* Groups all selected components.
|
||||
*/
|
||||
void groupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Ungroups all selected components.
|
||||
*/
|
||||
void ungroupSelectedComponents();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -41,18 +41,16 @@ import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.Template;
|
||||
import org.diylc.core.Theme;
|
||||
import org.diylc.core.measures.ResizeDimensions;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.filter.IComponentFilter;
|
||||
import org.diylc.test.ITestProcessor;
|
||||
|
||||
/**
|
||||
* Interface for communication between plug-ins and the application. Plug-ins may acquire
|
||||
* information or make changes through this interface. Application events are dispatched to plug-ins
|
||||
* through {@link MessageDispatcher}
|
||||
*
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
*
|
||||
* @see IPlugIn
|
||||
* @see MessageDispatcher
|
||||
* @see IMessageListener
|
||||
@@ -83,28 +81,21 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
public static final String HARDWARE_ACCELERATION = "hardwareAcceleration";
|
||||
public static final String EXTRA_SPACE_KEY = "extraSpace";
|
||||
public static final String FAVORITES_KEY = "favorites";
|
||||
public static final String DISABLED_CATEGORIES_KEY = "disabledComponentCategories";
|
||||
public static final String RENUMBER_ON_PASTE_KEY = "renumberOnPaste";
|
||||
public static final String RULER_IN_SUBDIVISION_KEY = "rulerInSubdivision";
|
||||
public static final String CACHING_ENABLED_KEY = "cachingEnabled";
|
||||
public static final String FONT_SCALE_FACTOR_KEY = "fontScaleFactor";
|
||||
public static final String SHOW_RESIZE_DIMENSIONS_TOOLTIP_KEY = "showResizeDimensionsTooltip";
|
||||
public static final String AUTO_UNIT_CONVERSION_KEY = "autoUnitConversion";
|
||||
|
||||
|
||||
|
||||
public static final String RULER_IN_SUBDIVISION_2 = "base of 2";
|
||||
public static final String RULER_IN_SUBDIVISION_10 = "base of 10";
|
||||
public static final String RULER_IN_SUBDIVISION_DEFAULT = RULER_IN_SUBDIVISION_10;
|
||||
|
||||
|
||||
public static final String SNAP_TO_NONE = "None";
|
||||
public static final String SNAP_TO_GRID = "Grid";
|
||||
public static final String SNAP_TO_COMPONENTS = "Components";
|
||||
public static final String SNAP_TO_DEFAULT = SNAP_TO_GRID;
|
||||
|
||||
public static final String SHOW_NODE_NAME_TOOLTIPS_KEY = "showNodeNameTooltips";
|
||||
|
||||
|
||||
public static final String LOCKED_ALPHA = "lockedAlpha";
|
||||
|
||||
|
||||
public static final String LANGUAGE = "language";
|
||||
public static final String LANGUAGE_DEFAULT = "English";
|
||||
|
||||
@@ -117,25 +108,25 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
public static final int NOBUTTON = 0;
|
||||
public static final int BUTTON1 = 1;
|
||||
public static final int BUTTON2 = 2;
|
||||
public static final int BUTTON3 = 3;
|
||||
public static final int BUTTON3 = 3;
|
||||
|
||||
/**
|
||||
* Returns size of the canvas that takes project dimensions into account as well as zoom level.
|
||||
* Each dimension is calculated as the product of the actual size and the number of pixels per
|
||||
* unit. If <code>useZoom</code> is set to true, the result is scaled by zoom factor.
|
||||
*
|
||||
*
|
||||
* @param useZoom
|
||||
* @param includeExtraSpace
|
||||
*
|
||||
*
|
||||
* @return canvas dimensions
|
||||
*/
|
||||
Dimension getCanvasDimensions(boolean useZoom, boolean includeExtraSpace);
|
||||
|
||||
/**
|
||||
* Returns an instance of {@link Cursor} that should be used at the specified location.
|
||||
*
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
*
|
||||
* @param point
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
@@ -146,14 +137,14 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
|
||||
/**
|
||||
* Returns an instance of currently loaded project.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Project getCurrentProject();
|
||||
|
||||
/**
|
||||
* Loads specified {@link Project}.
|
||||
*
|
||||
*
|
||||
* @param project
|
||||
* @param freshStart
|
||||
* @param filename file name when loading from a file
|
||||
@@ -167,22 +158,22 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
|
||||
/**
|
||||
* Loads a project from the specified file.
|
||||
*
|
||||
*
|
||||
* @param fileName
|
||||
*/
|
||||
void loadProjectFromFile(String fileName);
|
||||
|
||||
/**
|
||||
* Saves the current project into the specified file.
|
||||
*
|
||||
*
|
||||
* @param fileName
|
||||
* @param isBackup
|
||||
*/
|
||||
void saveProjectToFile(String fileName, boolean isBackup);
|
||||
|
||||
|
||||
/**
|
||||
* Exports the current project into one or more files - one per layer and potentially drill layer.
|
||||
*
|
||||
*
|
||||
* @param fileNameBase
|
||||
* @param g2d
|
||||
*/
|
||||
@@ -200,7 +191,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
|
||||
/**
|
||||
* Shows a user dialog if there are changes to confirm that it's safe to proceed.
|
||||
*
|
||||
*
|
||||
* @return true, if file actions (new, open, close) can be taken
|
||||
*/
|
||||
boolean allowFileAction();
|
||||
@@ -209,29 +200,15 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
* Returns all available {@link ComponentType}s classified by category. Result is a {@link Map}
|
||||
* between category name to a {@link List} of all {@link ComponentType}s that share that category
|
||||
* name.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Map<String, List<ComponentType>> getComponentTypes();
|
||||
|
||||
/**
|
||||
* Returns the {@link ComponentType}s that should be offered to the user, i.e. the result of
|
||||
* {@link #getComponentTypes()} without the categories the user disabled. Intended for component
|
||||
* browsers; anything that needs to resolve an arbitrary component class must use
|
||||
* {@link #getComponentTypes()} instead.
|
||||
*/
|
||||
Map<String, List<ComponentType>> getVisibleComponentTypes();
|
||||
|
||||
boolean isCategoryEnabled(String category);
|
||||
|
||||
void setCategoryEnabled(String category, boolean enabled);
|
||||
|
||||
void resetCategoryVisibility();
|
||||
|
||||
/**
|
||||
* Draws project on the provided {@link Graphics2D}. If the provided filter is not null, it will
|
||||
* be used to filter the components that are shown.
|
||||
*
|
||||
*
|
||||
* @param g2d
|
||||
* @param drawOptions specific drawing options
|
||||
* @param filter
|
||||
@@ -245,35 +222,35 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
|
||||
/**
|
||||
* Returns current zoom level where <code>zoomLevel = 1.0d</code> means 100%.
|
||||
*
|
||||
*
|
||||
* @return current zoom level
|
||||
*/
|
||||
double getZoomLevel();
|
||||
|
||||
/**
|
||||
* Changes current zoom level where <code>zoomLevel = 1.0d</code> means 100%
|
||||
*
|
||||
*
|
||||
* @param zoomLevel new zoom leve
|
||||
*/
|
||||
void setZoomLevel(double zoomLevel);
|
||||
|
||||
/**
|
||||
* Returns current version number.
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
VersionNumber getCurrentVersionNumber();
|
||||
|
||||
|
||||
/**
|
||||
* Returns few most recent versions.
|
||||
*
|
||||
* Returns few most recent versions.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Version> getRecentUpdates();
|
||||
|
||||
/**
|
||||
* Adds a list of components to the project.
|
||||
*
|
||||
*
|
||||
* @param componentTransferable
|
||||
* @param autoGroup
|
||||
* @param assignNewNames
|
||||
@@ -292,7 +269,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
|
||||
/**
|
||||
* Sets default value for the specified property name for currently selected component types.
|
||||
*
|
||||
*
|
||||
* @param propertyName display name for property
|
||||
* @param value new default value, must not be null
|
||||
*/
|
||||
@@ -300,7 +277,7 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
|
||||
/**
|
||||
* Sets default value for the specified property name for projects.
|
||||
*
|
||||
*
|
||||
* @param clazz class to set defaults to
|
||||
* @param propertyName display name for property
|
||||
* @param value new default value, must not be null
|
||||
@@ -314,15 +291,6 @@ public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyP
|
||||
*/
|
||||
List<PropertyWrapper> getMutualSelectionProperties();
|
||||
|
||||
/**
|
||||
* Available only during resizing, returns the dimensions of the component being resized.
|
||||
* Otherwise returns null.
|
||||
*
|
||||
* @return ResizeDimensions with width, height (in mm or in depending on configuration),
|
||||
* and length (if component implements IHaveLength), or null if not resizing
|
||||
*/
|
||||
ResizeDimensions getResizeDimensions();
|
||||
|
||||
void editSelection();
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.diylc.core.ExpansionMode;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
public interface ISelectionProcessor extends IGroupProcessor {
|
||||
public interface ISelectionProcessor {
|
||||
|
||||
/**
|
||||
* Returns the current {@link ComponentTransferable}.
|
||||
@@ -89,6 +89,16 @@ public interface ISelectionProcessor extends IGroupProcessor {
|
||||
*/
|
||||
void rotateSelection(int direction);
|
||||
|
||||
/**
|
||||
* Groups all selected components.
|
||||
*/
|
||||
void groupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Ungroups all selected components.
|
||||
*/
|
||||
void ungroupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Mirrors selected components in the given axis.
|
||||
*
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.diylc.common;
|
||||
import org.diylc.appframework.simplemq.MessageDispatcher;
|
||||
import org.diylc.plugins.chatbot.service.ChatbotService;
|
||||
import org.diylc.plugins.cloud.service.CloudService;
|
||||
import org.diylc.plugins.compare.service.CompareService;
|
||||
import org.diylc.presenter.DrawingManager;
|
||||
|
||||
public interface IServiceManager {
|
||||
@@ -12,8 +11,6 @@ public interface IServiceManager {
|
||||
|
||||
ChatbotService getChatbotService();
|
||||
|
||||
CompareService getCompareService();
|
||||
|
||||
MessageDispatcher<EventType> getMessageDispatcher();
|
||||
|
||||
DrawingManager getDrawingManager();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class Percentage implements Serializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private BigDecimal value;
|
||||
|
||||
public Percentage(BigDecimal value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Percentage(double value) {
|
||||
this.value = BigDecimal.valueOf(value);
|
||||
}
|
||||
|
||||
public Percentage(int value) {
|
||||
this.value = BigDecimal.valueOf((long) value);
|
||||
}
|
||||
|
||||
public BigDecimal getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(BigDecimal value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((value == null) ? 0 : value.stripTrailingZeros().hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Percentage other = (Percentage) obj;
|
||||
if (value == null) {
|
||||
if (other.value != null)
|
||||
return false;
|
||||
} else if (value.compareTo(other.value) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (value == null) return "null%";
|
||||
BigDecimal stripped = value.stripTrailingZeros();
|
||||
return String.format("%s%%", stripped.toPlainString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -24,11 +24,8 @@ package org.diylc.common;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.diylc.appframework.miscutils.ConfigurationManager;
|
||||
import org.diylc.core.IDynamicPropertySource;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
/**
|
||||
* Entity class for editable properties extracted from component objects. Represents a single
|
||||
@@ -68,8 +65,7 @@ public class PropertyWrapper implements Cloneable {
|
||||
public void readFrom(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException, SecurityException, NoSuchMethodException {
|
||||
this.ownerObject = object;
|
||||
Object value = getGetter().invoke(object);
|
||||
this.value = value;
|
||||
this.value = getGetter().invoke(object);
|
||||
}
|
||||
|
||||
// public void readUniqueFrom(IDIYComponent component)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.diylc.core.IDIYComponent;
|
||||
@@ -53,7 +52,6 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected UUID id = UUID.randomUUID();
|
||||
protected String name = "";
|
||||
|
||||
public static Color SELECTION_COLOR = Color.red;
|
||||
@@ -64,7 +62,6 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
public static Color LIGHT_METAL_COLOR = Color.decode("#EEEEEE");
|
||||
public static Color COPPER_COLOR = Color.decode("#DA8A67");
|
||||
public static Color GOLD_COLOR = Color.decode("#F4B301");
|
||||
public static Color BRASS_COLOR = Color.decode("#B8860B");
|
||||
public static Color FR4_COLOR = Color.decode("#6B9B6B");
|
||||
public static Color FR4_LIGHT_COLOR = Color.decode("#BABE71");
|
||||
public static Color PHENOLIC_COLOR = Color.decode("#F8EBB3");
|
||||
@@ -81,19 +78,6 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getId() {
|
||||
if (id == null) {
|
||||
id = UUID.randomUUID();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
return false;
|
||||
@@ -202,10 +186,6 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(this);
|
||||
|
||||
if (field.getName().equalsIgnoreCase("id")) {
|
||||
value = getId();
|
||||
}
|
||||
|
||||
// Deep copy point arrays.
|
||||
// TODO: something nicer
|
||||
if (value != null && value.getClass().isArray()
|
||||
@@ -295,38 +275,13 @@ public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPointMoveFreely(int pointIndex) {
|
||||
return true;
|
||||
public String[] getSectionNames(int pointIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void stretchBetween(Point2D first, Point2D second) {
|
||||
int count = getControlPointCount();
|
||||
// fresh instances because implementations are free to keep the point objects they are handed
|
||||
setControlPoint(new Point2D.Double(first.getX(), first.getY()), 0);
|
||||
if (count > 1) {
|
||||
setControlPoint(new Point2D.Double(second.getX(), second.getY()), count - 1);
|
||||
}
|
||||
for (int i = 1; i < count - 1; i++) {
|
||||
setControlPoint(getStretchedPoint(first, second, i), i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decides where a control point that is neither of the two ends lands when the component is
|
||||
* stretched between them, see {@link #stretchBetween(Point2D, Point2D)}. The default spaces the
|
||||
* points evenly along the straight line joining the ends. Override to place a point that carries
|
||||
* a meaning of its own, such as one that positions a label.
|
||||
*
|
||||
* @param first
|
||||
* @param second
|
||||
* @param index
|
||||
* @return position of the control point at the specified index.
|
||||
*/
|
||||
protected Point2D getStretchedPoint(Point2D first, Point2D second, int index) {
|
||||
double t = (double) index / (getControlPointCount() - 1);
|
||||
return new Point2D.Double(first.getX() + t * (second.getX() - first.getX()),
|
||||
first.getY() + t * (second.getY() - first.getY()));
|
||||
public boolean canPointMoveFreely(int pointIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
@@ -37,14 +37,16 @@ import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.LineStyle;
|
||||
import org.diylc.common.ObjectCache;
|
||||
import org.diylc.core.*;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComponent<T> implements
|
||||
IHaveLength {
|
||||
public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@@ -52,7 +54,6 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
|
||||
|
||||
public static Color GUIDELINE_COLOR = Color.blue;
|
||||
public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
|
||||
public static double CREATION_CURVATURE = 0.1;
|
||||
|
||||
// for backward compatibility
|
||||
protected Point2D[] controlPoints = null;
|
||||
@@ -150,7 +151,10 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
|
||||
path.curveTo(p[4].getX(), p[4].getY(), p[5].getX(), p[5].getY(), p[6].getX(), p[6].getY());
|
||||
}
|
||||
|
||||
Composite oldComposite = applyAlpha(g2d);
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
if (alpha < MAX_ALPHA) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
|
||||
}
|
||||
|
||||
drawCurve(path, g2d, componentState, drawingObserver);
|
||||
|
||||
@@ -288,72 +292,6 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Waves the curve from side to side instead of leaving the intermediate points on the straight
|
||||
* line joining the ends, so that a freshly created component reads as a slack wire that can be
|
||||
* reshaped rather than as a rigid line. Successive handles go to opposite sides, which turns the
|
||||
* default four point curve into an S, while the points that lie on the curve itself stay on the
|
||||
* straight line and the sine envelope fades the excursions out towards both ends. The first
|
||||
* excursion always points down the screen so that the shape does not depend on which end was
|
||||
* drawn first.
|
||||
* <p>
|
||||
* Keeping the on-curve points on the line is what makes the wave survive: a handle either side
|
||||
* of one of them then comes out as its exact mirror, which is the continuity rule that the
|
||||
* smoothing in {@link #draw} enforces, so that pass leaves the shape alone instead of pulling
|
||||
* one handle across to satisfy it.
|
||||
*/
|
||||
@Override
|
||||
protected Point2D getStretchedPoint(Point2D first, Point2D second, int index) {
|
||||
Point2D p = super.getStretchedPoint(first, second, index);
|
||||
double dx = second.getX() - first.getX();
|
||||
double dy = second.getY() - first.getY();
|
||||
double length = Math.hypot(dx, dy);
|
||||
if (length == 0 || isOnCurve(index)) {
|
||||
return p;
|
||||
}
|
||||
if (dx < 0 || (dx == 0 && dy > 0)) {
|
||||
dx = -dx;
|
||||
dy = -dy;
|
||||
}
|
||||
double t = (double) index / (getControlPointCount() - 1);
|
||||
double offset = getStretchedSide(index) * CREATION_CURVATURE * length * Math.sin(Math.PI * t);
|
||||
return new Point2D.Double(p.getX() - dy / length * offset, p.getY() + dx / length * offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true if the control point at the specified index lies on the curve rather than pulling
|
||||
* it from the side, which follows from how {@link #draw} chains the segments together.
|
||||
*/
|
||||
private boolean isOnCurve(int index) {
|
||||
if (index == 0 || index == getControlPointCount() - 1) {
|
||||
return true;
|
||||
}
|
||||
if (getPointCount() == PointCount.FIVE) {
|
||||
return index == 2;
|
||||
}
|
||||
if (getPointCount() == PointCount.SEVEN) {
|
||||
return index == 3;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return which side of the straight line the handle at the specified index is pushed to,
|
||||
* counting handles rather than control points so that an on-curve point in between does
|
||||
* not break the alternation.
|
||||
*/
|
||||
private int getStretchedSide(int index) {
|
||||
int handleCount = 0;
|
||||
for (int i = 1; i < index; i++) {
|
||||
if (!isOnCurve(i)) {
|
||||
handleCount++;
|
||||
}
|
||||
}
|
||||
return handleCount % 2 == 0 ? 1 : -1;
|
||||
}
|
||||
|
||||
private Point2D findThirdPoint(Point2D p0, Point2D p) {
|
||||
return new Point2D.Double(2 * p0.getX() - p.getX(), 2 * p0.getY() - p.getY());
|
||||
}
|
||||
@@ -399,12 +337,8 @@ public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComp
|
||||
// }
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Length")
|
||||
@EditableProperty
|
||||
public Size getLength() {
|
||||
return calculateLength();
|
||||
}
|
||||
|
||||
public Size calculateLength() {
|
||||
double d = 0;
|
||||
try {
|
||||
Point2D[] p = getControlPoints();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,424 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.components;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.diylc.appframework.miscutils.ConfigurationManager;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.LineStyle;
|
||||
import org.diylc.common.ObjectCache;
|
||||
import org.diylc.common.OrientationHV;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.IHaveLength;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
/**
|
||||
* Base class for connectors that run only horizontally and vertically and turn at rounded
|
||||
* 90-degree corners.
|
||||
* <p>
|
||||
* The first and the last control point are the sticky ends. Each control point in between is a free
|
||||
* bend vertex that the route reaches with a horizontal move followed by a vertical one, or the
|
||||
* other way around when {@link #getStartDirection()} is vertical. Both coordinates of a bend point
|
||||
* therefore carry meaning and the arrangement never has to be guessed: an orthogonal route of
|
||||
* <code>s</code> segments has <code>s - 2</code> degrees of freedom, and this template spends
|
||||
* exactly two per bend point. Segments of zero length collapse silently, which is how the simple L,
|
||||
* horizontal-vertical-horizontal and vertical-horizontal-vertical shapes are expressed: a bend
|
||||
* point sharing a column with the start swallows the leading segment, one sharing a row with the
|
||||
* end swallows the trailing one. All four combinations of leaving and arriving on either axis are
|
||||
* therefore reachable by dragging alone, which is why the start direction is not offered as a
|
||||
* property.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public abstract class AbstractOrthogonalComponent<T> extends AbstractTransparentComponent<T>
|
||||
implements IHaveLength {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
|
||||
public static Size DEFAULT_CORNER_RADIUS = new Size(0.05d, SizeUnit.in);
|
||||
|
||||
// rounding is skipped below this radius in pixels, where a quadratic corner is indistinguishable
|
||||
// from a sharp one
|
||||
private static final double MIN_CORNER_RADIUS = 1d;
|
||||
|
||||
private static final double EPSILON = 1e-6;
|
||||
|
||||
protected Point2D[] controlPoints = new Point2D[] {new Point2D.Double(0, 0),
|
||||
new Point2D.Double(DEFAULT_SIZE.convertToPixels() / 2, DEFAULT_SIZE.convertToPixels()),
|
||||
new Point2D.Double(DEFAULT_SIZE.convertToPixels(), DEFAULT_SIZE.convertToPixels())};
|
||||
|
||||
protected Color color = getDefaultColor();
|
||||
protected PointCount pointCount = PointCount.THREE;
|
||||
protected OrientationHV startDirection = OrientationHV.HORIZONTAL;
|
||||
protected LineStyle style = LineStyle.SOLID;
|
||||
protected Size cornerRadius = DEFAULT_CORNER_RADIUS;
|
||||
|
||||
/**
|
||||
* Draws the specified route onto graphics.
|
||||
*
|
||||
* @param curve
|
||||
* @param g2d
|
||||
* @param componentState
|
||||
* @param drawingObserver
|
||||
*/
|
||||
protected abstract void drawCurve(Path2D curve, Graphics2D g2d, ComponentState componentState,
|
||||
IDrawingObserver drawingObserver);
|
||||
|
||||
/**
|
||||
* @return default color.
|
||||
*/
|
||||
protected abstract Color getDefaultColor();
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, int width, int height) {
|
||||
Path2D path = createIconPath(width, height);
|
||||
g2d.setColor(getDefaultColor().darker());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
|
||||
g2d.draw(path);
|
||||
g2d.setColor(getDefaultColor());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.draw(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param width
|
||||
* @param height
|
||||
* @return the elbow drawn in the toolbox, so that subclasses that stroke it differently do not
|
||||
* have to restate the shape.
|
||||
*/
|
||||
protected Path2D createIconPath(int width, int height) {
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(1, height - 3);
|
||||
path.lineTo(width / 2d - 2, height - 3);
|
||||
path.quadTo(width / 2d, height - 3, width / 2d, height - 5);
|
||||
path.lineTo(width / 2d, 5);
|
||||
path.quadTo(width / 2d, 3, width / 2d + 2, 3);
|
||||
path.lineTo(width - 1, 3);
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||
IDrawingObserver drawingObserver) {
|
||||
if (checkPointsClipped(g2d.getClip())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Composite oldComposite = applyAlpha(g2d);
|
||||
|
||||
drawCurve(buildPath(), g2d, componentState, drawingObserver);
|
||||
|
||||
g2d.setComposite(oldComposite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands the control points into the vertices of the route. Every control point is reached by a
|
||||
* move along one axis followed by a move along the other, the end point included, so the loop
|
||||
* below is the whole routing rule. Zero-length segments are dropped as they are produced.
|
||||
*
|
||||
* @return route vertices, starting with the first and ending with the last control point.
|
||||
*/
|
||||
protected List<Point2D> buildVertices() {
|
||||
Point2D[] p = getControlPoints();
|
||||
boolean horizontalFirst = getStartDirection() == OrientationHV.HORIZONTAL;
|
||||
List<Point2D> vertices = new ArrayList<Point2D>();
|
||||
addVertex(vertices, p[0]);
|
||||
for (int i = 1; i < p.length; i++) {
|
||||
Point2D previous = p[i - 1];
|
||||
Point2D next = p[i];
|
||||
if (horizontalFirst) {
|
||||
addVertex(vertices, new Point2D.Double(next.getX(), previous.getY()));
|
||||
} else {
|
||||
addVertex(vertices, new Point2D.Double(previous.getX(), next.getY()));
|
||||
}
|
||||
addVertex(vertices, next);
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the route as a path with rounded corners. The radius is clamped to half of each adjacent
|
||||
* segment so that short segments bend rather than overshoot.
|
||||
*
|
||||
* @return path following the route.
|
||||
*/
|
||||
protected Path2D buildPath() {
|
||||
List<Point2D> vertices = buildVertices();
|
||||
double radius = getCornerRadius().convertToPixels();
|
||||
Path2D path = new Path2D.Double();
|
||||
Point2D first = vertices.get(0);
|
||||
path.moveTo(first.getX(), first.getY());
|
||||
for (int i = 1; i < vertices.size() - 1; i++) {
|
||||
Point2D previous = vertices.get(i - 1);
|
||||
Point2D corner = vertices.get(i);
|
||||
Point2D next = vertices.get(i + 1);
|
||||
double r = Math.min(radius, Math.min(previous.distance(corner), corner.distance(next)) / 2);
|
||||
if (r < MIN_CORNER_RADIUS) {
|
||||
path.lineTo(corner.getX(), corner.getY());
|
||||
continue;
|
||||
}
|
||||
Point2D in = interpolate(corner, previous, r);
|
||||
Point2D out = interpolate(corner, next, r);
|
||||
path.lineTo(in.getX(), in.getY());
|
||||
path.quadTo(corner.getX(), corner.getY(), out.getX(), out.getY());
|
||||
}
|
||||
Point2D last = vertices.get(vertices.size() - 1);
|
||||
path.lineTo(last.getX(), last.getY());
|
||||
return path;
|
||||
}
|
||||
|
||||
private static void addVertex(List<Point2D> vertices, Point2D p) {
|
||||
if (!vertices.isEmpty() && vertices.get(vertices.size() - 1).distance(p) < EPSILON) {
|
||||
return;
|
||||
}
|
||||
vertices.add(p);
|
||||
}
|
||||
|
||||
private static Point2D interpolate(Point2D from, Point2D towards, double distance) {
|
||||
double t = distance / from.distance(towards);
|
||||
return new Point2D.Double(from.getX() + (towards.getX() - from.getX()) * t, from.getY()
|
||||
+ (towards.getY() - from.getY()) * t);
|
||||
}
|
||||
|
||||
protected Point2D[] getControlPoints() {
|
||||
return this.controlPoints;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Point Count")
|
||||
public PointCount getPointCount() {
|
||||
if (pointCount == null) {
|
||||
pointCount = PointCount.THREE;
|
||||
}
|
||||
return pointCount;
|
||||
}
|
||||
|
||||
public void setPointCount(PointCount pointCount) {
|
||||
if (getPointCount() == pointCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point2D[] p = getControlPoints();
|
||||
Point2D start = p[0];
|
||||
Point2D end = p[p.length - 1];
|
||||
Point2D[] newPoints = new Point2D[pointCount.count];
|
||||
newPoints[0] = start;
|
||||
newPoints[pointCount.count - 1] = end;
|
||||
|
||||
int bendCount = pointCount.count - 2;
|
||||
for (int i = 1; i <= bendCount; i++) {
|
||||
newPoints[i] = getBendPoint(start, end, i, bendCount);
|
||||
}
|
||||
|
||||
this.controlPoints = newPoints;
|
||||
this.pointCount = pointCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Point2D getStretchedPoint(Point2D first, Point2D second, int index) {
|
||||
return getBendPoint(first, second, index, getControlPointCount() - 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Spreads the bend points so that the route comes out as an even staircase: they advance evenly
|
||||
* along the axis the route travels last, and sit halfway between those steps on the other axis.
|
||||
*
|
||||
* @param start
|
||||
* @param end
|
||||
* @param index
|
||||
* @param bendCount number of control points between the two ends
|
||||
* @return position of the bend point at the specified index.
|
||||
*/
|
||||
private Point2D getBendPoint(Point2D start, Point2D end, int index, int bendCount) {
|
||||
double along = (double) index / bendCount;
|
||||
double across = (2d * index - 1) / (2d * bendCount);
|
||||
boolean horizontalFirst = getStartDirection() == OrientationHV.HORIZONTAL;
|
||||
double tx = horizontalFirst ? across : along;
|
||||
double ty = horizontalFirst ? along : across;
|
||||
return new Point2D.Double(start.getX() + (end.getX() - start.getX()) * tx, start.getY()
|
||||
+ (end.getY() - start.getY()) * ty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not an editable property on purpose. Every route shape is reachable by dragging the bend
|
||||
* points, so exposing this would only give the user a second, less discoverable way to do the
|
||||
* same thing. It is kept as state because a quarter-turn rotation swaps the two axes and the
|
||||
* transformer has to record that.
|
||||
*
|
||||
* @return axis the route travels along when it leaves the first control point.
|
||||
*/
|
||||
public OrientationHV getStartDirection() {
|
||||
if (startDirection == null) {
|
||||
startDirection = OrientationHV.HORIZONTAL;
|
||||
}
|
||||
return startDirection;
|
||||
}
|
||||
|
||||
public void setStartDirection(OrientationHV startDirection) {
|
||||
this.startDirection = startDirection;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Corner Radius")
|
||||
public Size getCornerRadius() {
|
||||
if (cornerRadius == null) {
|
||||
cornerRadius = DEFAULT_CORNER_RADIUS;
|
||||
}
|
||||
return cornerRadius;
|
||||
}
|
||||
|
||||
public void setCornerRadius(Size cornerRadius) {
|
||||
this.cornerRadius = cornerRadius;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Color")
|
||||
public Color getLeadColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setLeadColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Style")
|
||||
public LineStyle getStyle() {
|
||||
if (style == null) {
|
||||
style = LineStyle.SOLID;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
public void setStyle(LineStyle style) {
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Length")
|
||||
public Size getLength() {
|
||||
return calculateLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Size calculateLength() {
|
||||
// corner rounding shaves a fraction of the radius off each bend, which is well below the
|
||||
// precision this readout is used at
|
||||
List<Point2D> vertices = buildVertices();
|
||||
double d = 0;
|
||||
for (int i = 1; i < vertices.size(); i++) {
|
||||
d += vertices.get(i - 1).distance(vertices.get(i));
|
||||
}
|
||||
|
||||
SizeUnit unit;
|
||||
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.METRIC_KEY, true)) {
|
||||
unit = SizeUnit.mm;
|
||||
} else {
|
||||
unit = SizeUnit.in;
|
||||
}
|
||||
|
||||
return new Size(d * SizeUnit.px.getFactor() / unit.getFactor(), unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlPointCount() {
|
||||
return getControlPoints().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2D getControlPoint(int index) {
|
||||
return getControlPoints()[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoint(Point2D point, int index) {
|
||||
getControlPoints()[index].setLocation(point);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControlPointSticky(int index) {
|
||||
return index == 0 || index == getControlPointCount() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
return index > 0 && index < getControlPointCount() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
|
||||
return VisibilityPolicy.WHEN_SELECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getCachingBounds() {
|
||||
double minX = Integer.MAX_VALUE;
|
||||
double maxX = Integer.MIN_VALUE;
|
||||
double minY = Integer.MAX_VALUE;
|
||||
double maxY = Integer.MIN_VALUE;
|
||||
double margin = 50; // hard coded, replace with something meaningful
|
||||
// every route vertex borrows both of its coordinates from a control point, so the control
|
||||
// points alone bound the whole route
|
||||
for (int i = 0; i < getControlPointCount(); i++) {
|
||||
Point2D p = getControlPoint(i);
|
||||
if (p.getX() < minX) {
|
||||
minX = p.getX();
|
||||
}
|
||||
if (p.getX() > maxX) {
|
||||
maxX = p.getX();
|
||||
}
|
||||
if (p.getY() < minY) {
|
||||
minY = p.getY();
|
||||
}
|
||||
if (p.getY() > maxY) {
|
||||
maxY = p.getY();
|
||||
}
|
||||
}
|
||||
|
||||
return new Rectangle2D.Double(minX - margin, minY - margin, maxX - minX + 2 * margin, maxY - minY
|
||||
+ 2 * margin);
|
||||
}
|
||||
|
||||
public enum PointCount {
|
||||
THREE(3), FOUR(4), FIVE(5);
|
||||
|
||||
private int count;
|
||||
|
||||
private PointCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-43
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -22,57 +22,24 @@
|
||||
package org.diylc.components;
|
||||
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.common.Percentage;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class AbstractTransparentComponent<T> extends AbstractComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final boolean OUTLINE_MODE_WHILE_DRAGGING = false;
|
||||
|
||||
public static byte MAX_ALPHA_LEGACY = Byte.MAX_VALUE;
|
||||
public static int MAX_ALPHA = 100;
|
||||
public static byte MAX_ALPHA = 127;
|
||||
|
||||
@Deprecated
|
||||
protected Byte alpha;
|
||||
protected Byte alpha = MAX_ALPHA;
|
||||
|
||||
protected Percentage alphaPercent = new Percentage(100);
|
||||
|
||||
@EditableProperty(name = "Alpha")
|
||||
public Percentage getAlpha() {
|
||||
if (alphaPercent == null) {
|
||||
if (alpha != null) {
|
||||
alphaPercent = new Percentage(Math.round(100f * alpha / MAX_ALPHA_LEGACY));
|
||||
alpha = null;
|
||||
} else {
|
||||
alphaPercent = new Percentage(100);
|
||||
}
|
||||
@EditableProperty
|
||||
public Byte getAlpha() {
|
||||
if (alpha == null) {
|
||||
alpha = MAX_ALPHA;
|
||||
}
|
||||
return alphaPercent;
|
||||
return alpha;
|
||||
}
|
||||
|
||||
public void setAlpha(Percentage alphaPercent) {
|
||||
this.alphaPercent = alphaPercent;
|
||||
}
|
||||
|
||||
public Composite applyAlpha(Graphics2D g2d, ComponentState componentState) {
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
double alpha = (OUTLINE_MODE_WHILE_DRAGGING && componentState == ComponentState.DRAGGING) ? 0 :
|
||||
getAlpha().getValue().doubleValue();
|
||||
if (alpha < MAX_ALPHA) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)(alpha / 100d)));
|
||||
}
|
||||
return oldComposite;
|
||||
}
|
||||
|
||||
public Composite applyAlpha(Graphics2D g2d) {
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
double alpha = getAlpha().getValue().doubleValue();
|
||||
if (alpha < MAX_ALPHA) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float)(alpha / 100d)));
|
||||
}
|
||||
return oldComposite;
|
||||
public void setAlpha(Byte alpha) {
|
||||
this.alpha = alpha;
|
||||
}
|
||||
}
|
||||
|
||||
-370
@@ -1,370 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.components.composite;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.diylc.components.AbstractComponent;
|
||||
import org.diylc.components.AbstractTransparentComponent;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.VisibilityPolicy;
|
||||
import org.diylc.core.annotations.BomPolicy;
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
/**
|
||||
* Instantiation of a {@code BuildingBlock} as a single, rigid component rather than a group of
|
||||
* loose ones. Wraps an embedded list of child components and aggregates their control points,
|
||||
* so it can be placed, moved, rotated and wired up like any other component while the netlist,
|
||||
* BOM and AI project description still see its individual terminals (see
|
||||
* {@link #getControlPointNodeName(int)}).
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
@ComponentDescriptor(
|
||||
name = "Building Block",
|
||||
description = "A group of components instantiated as a single rigid component",
|
||||
category = "Building Blocks",
|
||||
author = "Branislav Stojkovic",
|
||||
instanceNamePrefix = "BLK",
|
||||
zOrder = IDIYComponent.COMPONENT,
|
||||
flexibleZOrder = true,
|
||||
bomPolicy = BomPolicy.SHOW_ALL_NAMES,
|
||||
autoEdit = false,
|
||||
enableCache = false,
|
||||
transformer = CompositeComponentTransformer.class,
|
||||
hiddenInPalette = true)
|
||||
public class CompositeComponent extends AbstractTransparentComponent<String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private List<IDIYComponent<?>> childComponents = new ArrayList<IDIYComponent<?>>();
|
||||
|
||||
// Name of the building block this instance was created from. Drives its display identity in
|
||||
// the BOM, netlist report and AI project description (see ComponentProcessor.getDisplayTypeName).
|
||||
private String blockName;
|
||||
|
||||
// Free-form label the user can edit after placement, independent of blockName. Shown in the BOM.
|
||||
private String value;
|
||||
|
||||
// Flat index mapping a composite control point index to (child ordinal, child point index).
|
||||
// Rebuilt lazily since children never change after construction and the arrays are not
|
||||
// serialized (transient).
|
||||
private transient int[] childOf;
|
||||
private transient int[] pointOf;
|
||||
private transient String[] nodeNameOf;
|
||||
|
||||
/**
|
||||
* Required no-arg constructor, used reflectively by {@code ComponentProcessor} and XStream.
|
||||
*/
|
||||
public CompositeComponent() {
|
||||
super();
|
||||
}
|
||||
|
||||
private void buildIndexIfNeeded() {
|
||||
if (childOf != null) {
|
||||
return;
|
||||
}
|
||||
int total = 0;
|
||||
for (IDIYComponent<?> c : childComponents) {
|
||||
total += c.getControlPointCount();
|
||||
}
|
||||
int[] newChildOf = new int[total];
|
||||
int[] newPointOf = new int[total];
|
||||
int idx = 0;
|
||||
for (int ci = 0; ci < childComponents.size(); ci++) {
|
||||
IDIYComponent<?> c = childComponents.get(ci);
|
||||
int count = c.getControlPointCount();
|
||||
for (int pi = 0; pi < count; pi++) {
|
||||
newChildOf[idx] = ci;
|
||||
newPointOf[idx] = pi;
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
nodeNameOf = buildNodeNames(newChildOf, newPointOf);
|
||||
pointOf = newPointOf;
|
||||
// assigned last, it is what marks the index as built
|
||||
childOf = newChildOf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the node names the composite exposes. A child's own node name is kept unchanged
|
||||
* whenever it is unique, so the pads of a custom board read "VCC" rather than "Pad3.VCC" - the
|
||||
* pad's component name is an arbitrary leftover from the project the block was saved in.
|
||||
* Clashing names are resolved in two passes: pins of multi-point children are qualified with the
|
||||
* child's name ("R1.1", "R2.1"), then whatever still clashes, typically several pads sharing a
|
||||
* name, gets a numeric suffix in save order ("GND_1", "GND_2").
|
||||
*
|
||||
* <p>Only sticky, named points take part. Non-sticky points never become netlist nodes, and a
|
||||
* board's corner points would otherwise force a rename on a pad that shares their default
|
||||
* numeric name.
|
||||
*/
|
||||
private String[] buildNodeNames(int[] newChildOf, int[] newPointOf) {
|
||||
String[] names = new String[newChildOf.length];
|
||||
boolean[] terminal = new boolean[newChildOf.length];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IDIYComponent<?> child = childComponents.get(newChildOf[i]);
|
||||
names[i] = child.getControlPointNodeName(newPointOf[i]);
|
||||
terminal[i] = names[i] != null && child.isControlPointSticky(newPointOf[i]);
|
||||
}
|
||||
|
||||
Set<String> clashing = findClashingNames(names, terminal);
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
IDIYComponent<?> child = childComponents.get(newChildOf[i]);
|
||||
String childName = child.getName();
|
||||
if (terminal[i] && clashing.contains(names[i]) && child.getControlPointCount() > 1
|
||||
&& childName != null && !childName.trim().isEmpty()) {
|
||||
names[i] = childName.trim() + "." + names[i];
|
||||
}
|
||||
}
|
||||
|
||||
clashing = findClashingNames(names, terminal);
|
||||
if (clashing.isEmpty()) {
|
||||
return names;
|
||||
}
|
||||
Set<String> taken = new HashSet<String>();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (terminal[i] && !clashing.contains(names[i])) {
|
||||
taken.add(names[i]);
|
||||
}
|
||||
}
|
||||
Map<String, Integer> nextSuffix = new HashMap<String, Integer>();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (terminal[i] && clashing.contains(names[i])) {
|
||||
int suffix = nextSuffix.getOrDefault(names[i], 1);
|
||||
while (taken.contains(names[i] + "_" + suffix)) {
|
||||
suffix++;
|
||||
}
|
||||
nextSuffix.put(names[i], suffix + 1);
|
||||
names[i] = names[i] + "_" + suffix;
|
||||
taken.add(names[i]);
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
private static Set<String> findClashingNames(String[] names, boolean[] terminal) {
|
||||
Set<String> seen = new HashSet<String>();
|
||||
Set<String> clashing = new HashSet<String>();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (terminal[i] && !seen.add(names[i])) {
|
||||
clashing.add(names[i]);
|
||||
}
|
||||
}
|
||||
return clashing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the embedded child components, in save order. Never {@code null}.
|
||||
*/
|
||||
public List<IDIYComponent<?>> getChildComponents() {
|
||||
if (childComponents == null) {
|
||||
childComponents = new ArrayList<IDIYComponent<?>>();
|
||||
}
|
||||
return childComponents;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Block", defaultable = false, sortOrder = 1)
|
||||
public String getBlockName() {
|
||||
return blockName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the source block name. Deliberately not named {@code setBlockName} so that
|
||||
* {@code ComponentProcessor}'s getter/setter matching does not turn the "Block" property
|
||||
* editable in the property editor - it is metadata about the instance, not a value the user
|
||||
* should be able to change after placement.
|
||||
*/
|
||||
public void initBlockName(String blockName) {
|
||||
this.blockName = blockName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlPointCount() {
|
||||
buildIndexIfNeeded();
|
||||
return childOf.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2D getControlPoint(int index) {
|
||||
buildIndexIfNeeded();
|
||||
return childComponents.get(childOf[index]).getControlPoint(pointOf[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoint(Point2D point, int index) {
|
||||
buildIndexIfNeeded();
|
||||
childComponents.get(childOf[index]).setControlPoint(point, pointOf[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControlPointSticky(int index) {
|
||||
buildIndexIfNeeded();
|
||||
return childComponents.get(childOf[index]).isControlPointSticky(pointOf[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
buildIndexIfNeeded();
|
||||
return childComponents.get(childOf[index]).canControlPointOverlap(pointOf[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
|
||||
buildIndexIfNeeded();
|
||||
return childComponents.get(childOf[index]).getControlPointVisibilityPolicy(pointOf[index]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getControlPointNodeName(int index) {
|
||||
buildIndexIfNeeded();
|
||||
return nodeNameOf[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* The composite is always rigid: it moves and rotates as a unit and never stretches. See design
|
||||
* decision D4 in {@code docs/plans/composite-building-blocks.md}.
|
||||
*/
|
||||
@Override
|
||||
public boolean canPointMoveFreely(int pointIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createdIn(Project project) {
|
||||
for (IDIYComponent<?> c : getChildComponents()) {
|
||||
c.createdIn(project);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@EditableProperty
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||
IDrawingObserver drawingObserver) {
|
||||
Composite oldComposite = applyAlpha(g2d, componentState);
|
||||
for (IDIYComponent<?> c : getChildComponents()) {
|
||||
// Children always draw in their normal state - the composite draws its own selection
|
||||
// outline below instead of letting every child paint its own highlight.
|
||||
c.draw(g2d, componentState, outlineMode, project, drawingObserver);
|
||||
}
|
||||
g2d.setComposite(oldComposite);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, int width, int height) {
|
||||
// Must not touch `components` - ComponentProcessor draws this on a default-constructed,
|
||||
// childless instance to build the palette icon.
|
||||
g2d.setColor(LIGHT_METAL_COLOR);
|
||||
g2d.fillRect(2, 2, width - 4, height - 4);
|
||||
g2d.setColor(METAL_COLOR);
|
||||
g2d.drawRect(2, 2, width - 4, height - 4);
|
||||
int halfW = width / 2;
|
||||
int halfH = height / 2;
|
||||
g2d.drawLine(halfW, 2, halfW, height - 2);
|
||||
g2d.drawLine(2, halfH, width - 2, halfH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep-clones the composite together with all its children, so that two placed instances never
|
||||
* share child objects (that would make moving one instance move the other - see the "clone()
|
||||
* is the sharp edge" risk in {@code docs/plans/composite-building-blocks.md}). Preserves this
|
||||
* component's own id and every child's id, matching {@link AbstractComponent#clone()}'s
|
||||
* contract of copying identity by default - callers that need a genuinely new component
|
||||
* reassign ids themselves, exactly as {@code BuildingBlockManager.loadBlock} does when it
|
||||
* clones each source component individually to place a brand new instance of a block. This also
|
||||
* keeps id-sensitive reflective comparisons (like the default {@code equalsTo} most child
|
||||
* component classes inherit) working correctly between a composite and its own clone, which the
|
||||
* undo dirty-check in {@code Presenter.notifyProjectModifiedIfNeeded} relies on.
|
||||
*/
|
||||
@Override
|
||||
public IDIYComponent<String> clone() throws CloneNotSupportedException {
|
||||
CompositeComponent clone = new CompositeComponent();
|
||||
clone.setId(getId());
|
||||
clone.setName(getName());
|
||||
clone.blockName = this.blockName;
|
||||
clone.value = this.value;
|
||||
// matches AbstractComponent.clone(), which shallow-copies the Percentage reference
|
||||
clone.setAlpha(getAlpha());
|
||||
List<IDIYComponent<?>> clonedComponents = new ArrayList<IDIYComponent<?>>(getChildComponents().size());
|
||||
for (IDIYComponent<?> c : getChildComponents()) {
|
||||
clonedComponents.add(c.clone());
|
||||
}
|
||||
clone.childComponents = clonedComponents;
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden because {@link AbstractComponent#equalsTo(IDIYComponent)} compares the
|
||||
* {@code components} field with {@code List.equals()}, which falls back to child object
|
||||
* identity since no component class overrides {@code Object.equals()} - two structurally
|
||||
* identical composites built from different object graphs (e.g. an original and its clone)
|
||||
* would otherwise never compare equal, defeating the undo dirty-check in
|
||||
* {@code Presenter.notifyProjectModifiedIfNeeded}.
|
||||
*/
|
||||
@Override
|
||||
public boolean equalsTo(IDIYComponent<?> other) {
|
||||
if (!(other instanceof CompositeComponent)) {
|
||||
return false;
|
||||
}
|
||||
CompositeComponent o = (CompositeComponent) other;
|
||||
if (!Objects.equals(getName(), o.getName()) || !Objects.equals(blockName, o.blockName)
|
||||
|| !Objects.equals(value, o.value) || !Objects.equals(getAlpha(), o.getAlpha())) {
|
||||
return false;
|
||||
}
|
||||
List<IDIYComponent<?>> otherComponents = o.getChildComponents();
|
||||
if (getChildComponents().size() != otherComponents.size()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < childComponents.size(); i++) {
|
||||
if (!childComponents.get(i).equalsTo(otherComponents.get(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.components.composite;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.IComponentTransformer;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.presenter.ComponentProcessor;
|
||||
|
||||
/**
|
||||
* Rotates and mirrors a {@link CompositeComponent} by delegating to each child's own
|
||||
* {@link IComponentTransformer}, around the same centre for every child so the assembly stays
|
||||
* geometrically consistent. If any child's type cannot rotate (or mirror), the whole composite
|
||||
* reports that it cannot either - silently leaving one child un-rotated would be worse (see
|
||||
* design decision D9 in {@code docs/plans/composite-building-blocks.md}).
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class CompositeComponentTransformer implements IComponentTransformer {
|
||||
|
||||
@Override
|
||||
public boolean canRotate(IDIYComponent<?> component) {
|
||||
CompositeComponent composite = (CompositeComponent) component;
|
||||
if (composite.getChildComponents().isEmpty())
|
||||
return false;
|
||||
for (IDIYComponent<?> child : composite.getChildComponents()) {
|
||||
if (!childTransformer(child).canRotate(child))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMirror(IDIYComponent<?> component) {
|
||||
CompositeComponent composite = (CompositeComponent) component;
|
||||
if (composite.getChildComponents().isEmpty())
|
||||
return false;
|
||||
for (IDIYComponent<?> child : composite.getChildComponents()) {
|
||||
if (!childTransformer(child).canMirror(child))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mirroringChangesCircuit() {
|
||||
// This transformer instance is shared by every CompositeComponent (ComponentProcessor caches
|
||||
// one instance per class), so it has no access to a specific composite's children here.
|
||||
// Conservatively assume mirroring can change the circuit, so the user is always warned - a
|
||||
// spurious confirmation is far cheaper than silently flipping a board's pinout.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
CompositeComponent composite = (CompositeComponent) component;
|
||||
for (IDIYComponent<?> child : composite.getChildComponents()) {
|
||||
childTransformer(child).rotate(child, center, direction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mirror(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
CompositeComponent composite = (CompositeComponent) component;
|
||||
for (IDIYComponent<?> child : composite.getChildComponents()) {
|
||||
childTransformer(child).mirror(child, center, direction);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private IComponentTransformer childTransformer(IDIYComponent<?> child) {
|
||||
ComponentType type =
|
||||
ComponentProcessor.getInstance().extractComponentTypeFrom((Class) child.getClass());
|
||||
return type.getTransformer();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.components.transform;
|
||||
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
import org.diylc.common.OrientationHV;
|
||||
import org.diylc.components.AbstractOrthogonalComponent;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Rotates and mirrors orthogonal connectors. Quarter-turn rotation turns every horizontal run of
|
||||
* the route into a vertical one, so the start direction has to follow the points. Mirroring leaves
|
||||
* both axes in place and needs nothing beyond moving the points.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class OrthogonalComponentTransformer extends SimpleComponentTransformer {
|
||||
|
||||
@Override
|
||||
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
super.rotate(component, center, direction);
|
||||
if (component instanceof AbstractOrthogonalComponent<?> orthogonal) {
|
||||
orthogonal.setStartDirection(orthogonal.getStartDirection() == OrientationHV.HORIZONTAL
|
||||
? OrientationHV.VERTICAL : OrientationHV.HORIZONTAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.diylc.core;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ComponentGroup implements Serializable {
|
||||
|
||||
private Set<UUID> componentIds;
|
||||
private String name;
|
||||
|
||||
public ComponentGroup(Set<UUID> componentIds) {
|
||||
this.componentIds = componentIds;
|
||||
}
|
||||
|
||||
public ComponentGroup(Set<UUID> componentIds, String name) {
|
||||
this.componentIds = componentIds;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static ComponentGroup from(Collection<IDIYComponent<?>> components, String name) {
|
||||
Set<UUID> componentIds = components.stream()
|
||||
.map(IDIYComponent::getId)
|
||||
.filter(id -> id != null)
|
||||
.collect(Collectors.toSet());
|
||||
return new ComponentGroup(componentIds, name);
|
||||
}
|
||||
|
||||
public Set<UUID> getComponentIds() {
|
||||
return componentIds;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
*
|
||||
* This file is part of DIYLC.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -25,7 +25,6 @@ import java.awt.Graphics2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
@@ -56,10 +55,6 @@ public interface IDIYComponent<T> extends Serializable, Cloneable {
|
||||
public static final int WIRING = 5;
|
||||
public static final int TEXT = 6;
|
||||
|
||||
UUID getId();
|
||||
|
||||
void setId(UUID id);
|
||||
|
||||
/**
|
||||
* @return component instance name.
|
||||
*/
|
||||
@@ -105,17 +100,6 @@ public interface IDIYComponent<T> extends Serializable, Cloneable {
|
||||
*/
|
||||
void setControlPoint(Point2D point, int index);
|
||||
|
||||
/**
|
||||
* Positions the component so that it spans the two points, which is how components created with
|
||||
* <code>CreationMethod.POINT_BY_POINT</code> are shaped while the user is placing them. The first
|
||||
* and the last control point go to the two ends; where the points in between land is up to the
|
||||
* component.
|
||||
*
|
||||
* @param first
|
||||
* @param second
|
||||
*/
|
||||
void stretchBetween(Point2D first, Point2D second);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true, if the specified control point may stick to control points of other components.
|
||||
@@ -148,6 +132,13 @@ public interface IDIYComponent<T> extends Serializable, Cloneable {
|
||||
*/
|
||||
String getInternalLinkName(int index1, int index2);
|
||||
|
||||
/**
|
||||
* @param pointIndex
|
||||
* @return name of the internal section containing the specified point, or null if the component does not have internal sections.
|
||||
* One point can be shared between multiple sections, in which case, the result may contain more than one element.
|
||||
*/
|
||||
String[] getSectionNames(int pointIndex);
|
||||
|
||||
/**
|
||||
* @param pointIndex
|
||||
* @return true if the control point can move without affecting other points' position, false otherwise
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.core;
|
||||
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
public interface IHaveLength {
|
||||
|
||||
Size calculateLength();
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -23,9 +23,13 @@ package org.diylc.core;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.diylc.appframework.update.VersionNumber;
|
||||
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
@@ -63,7 +67,6 @@ public class Project implements Serializable, Cloneable {
|
||||
private Integer dotSpacing;
|
||||
private List<IDIYComponent<?>> components;
|
||||
private Set<Set<IDIYComponent<?>>> groups;
|
||||
private Set<ComponentGroup> groupsEx;
|
||||
private Set<Integer> lockedLayers;
|
||||
private Set<IDIYComponent<?>> lockedComponents;
|
||||
private Set<Integer> hiddenLayers;
|
||||
@@ -72,7 +75,6 @@ public class Project implements Serializable, Cloneable {
|
||||
public Project() {
|
||||
components = new ArrayList<IDIYComponent<?>>();
|
||||
groups = new HashSet<Set<IDIYComponent<?>>>();
|
||||
groupsEx = new HashSet<>();
|
||||
lockedLayers = new HashSet<Integer>();
|
||||
hiddenLayers = new HashSet<Integer>();
|
||||
lockedComponents = new HashSet<IDIYComponent<?>>();
|
||||
@@ -151,35 +153,22 @@ public class Project implements Serializable, Cloneable {
|
||||
|
||||
/**
|
||||
* List of components sorted by z-order ascending.
|
||||
* s
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<IDIYComponent<?>> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public Set<ComponentGroup> getGroupsEx() {
|
||||
if (groupsEx == null) {
|
||||
groupsEx = new HashSet<>();
|
||||
|
||||
if (groups != null && !groups.isEmpty()) {
|
||||
for (Set<IDIYComponent<?>> group : groups) {
|
||||
Set<IDIYComponent<?>> nonNullIds =
|
||||
group.stream().filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
if (!nonNullIds.isEmpty()) {
|
||||
ComponentGroup newGroup = ComponentGroup.from(group, null);
|
||||
groupsEx.add(newGroup);
|
||||
}
|
||||
}
|
||||
groups.clear();
|
||||
}
|
||||
}
|
||||
groupsEx.removeAll(groupsEx.stream().
|
||||
filter(x -> x.getComponentIds() == null ||
|
||||
x.getComponentIds().stream().noneMatch(Objects::nonNull)).collect(Collectors.toSet()));
|
||||
return groupsEx;
|
||||
/**
|
||||
* Set of grouped components.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Set<IDIYComponent<?>>> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
|
||||
public Set<IDIYComponent<?>> getLockedComponents() {
|
||||
if (lockedComponents == null)
|
||||
lockedComponents = new HashSet<IDIYComponent<?>>();
|
||||
@@ -303,11 +292,6 @@ public class Project implements Serializable, Cloneable {
|
||||
return false;
|
||||
} else if (!groups.equals(other.groups))
|
||||
return false;
|
||||
if (groupsEx == null) {
|
||||
if (other.groupsEx != null)
|
||||
return false;
|
||||
} else if (!groupsEx.equals(other.groupsEx))
|
||||
return false;
|
||||
if (lockedLayers == null) {
|
||||
if (other.lockedLayers != null)
|
||||
return false;
|
||||
@@ -372,15 +356,12 @@ public class Project implements Serializable, Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
for (ComponentGroup group : this.getGroupsEx()) {
|
||||
// Filter out null IDs when cloning groups
|
||||
Set<UUID> validIds = group.getComponentIds().stream()
|
||||
.filter(id -> id != null)
|
||||
.collect(Collectors.toSet());
|
||||
// Only add group if it has valid component IDs
|
||||
if (!validIds.isEmpty()) {
|
||||
project.getGroupsEx().add(new ComponentGroup(validIds, group.getName()));
|
||||
for (Set<IDIYComponent<?>> group : this.groups) {
|
||||
Set<IDIYComponent<?>> cloneGroup = new HashSet<IDIYComponent<?>>();
|
||||
for (IDIYComponent<?> component : group) {
|
||||
cloneGroup.add(cloneMap.get(component));
|
||||
}
|
||||
project.groups.add(cloneGroup);
|
||||
}
|
||||
|
||||
for (IDIYComponent<?> component : this.getLockedComponents()) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
Copyright (c) 2009-2018 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
@@ -123,18 +123,9 @@ public @interface ComponentDescriptor {
|
||||
boolean enableDatasheet() default false;
|
||||
|
||||
/**
|
||||
* If datasheet is enabled, this property determines how many columns define a component, e.g. in how many steps we can instantiate a component
|
||||
*
|
||||
* If datasheet is enabled, this property determines how many columns define a component, e.g. in how many steps we can instantiate a component
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int datasheetCreationStepCount() default 0;
|
||||
|
||||
/**
|
||||
* @return true if the component type should not be listed in the palette (toolbox and
|
||||
* component tree), while still being resolvable via
|
||||
* {@code ComponentProcessor.extractComponentTypeFrom} for netlist, BOM and name
|
||||
* generation purposes. Used by component types that are only ever created
|
||||
* programmatically, e.g. {@code CompositeComponent}.
|
||||
*/
|
||||
boolean hiddenInPalette() default false;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user