mavenize
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.io.Serializable;
|
||||
|
||||
public class Announcement implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String title;
|
||||
private String text;
|
||||
private String date;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(String date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((date == null) ? 0 : date.hashCode());
|
||||
result = prime * result + ((text == null) ? 0 : text.hashCode());
|
||||
result = prime * result + ((title == null) ? 0 : title.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;
|
||||
Announcement other = (Announcement) obj;
|
||||
if (date == null) {
|
||||
if (other.date != null)
|
||||
return false;
|
||||
} else if (!date.equals(other.date))
|
||||
return false;
|
||||
if (text == null) {
|
||||
if (other.text != null)
|
||||
return false;
|
||||
} else if (!text.equals(other.text))
|
||||
return false;
|
||||
if (title == null) {
|
||||
if (other.title != null)
|
||||
return false;
|
||||
} else if (!title.equals(other.title))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.diylc.appframework.miscutils.ConfigurationManager;
|
||||
import org.diylc.plugins.cloud.model.IServiceAPI;
|
||||
import com.diyfever.httpproxy.PhpFlatProxy;
|
||||
import com.diyfever.httpproxy.ProxyFactory;
|
||||
|
||||
public class AnnouncementProvider {
|
||||
|
||||
private String serviceUrl = "http://www.diy-fever.com/diylc/api/v1/announcements.html";
|
||||
private String LAST_READ_KEY = "announcement.lastReadDate";
|
||||
private String USER_ID_KEY = "userId";
|
||||
|
||||
private IAnnouncementService service;
|
||||
|
||||
private Date lastDate;
|
||||
private List<Announcement> announcements;
|
||||
|
||||
private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
public AnnouncementProvider() {
|
||||
String lastDateStr = ConfigurationManager.getInstance().readString(LAST_READ_KEY, null);
|
||||
try {
|
||||
this.lastDate = lastDateStr == null ? null : dateFormat.parse(lastDateStr);
|
||||
} catch (ParseException e) {
|
||||
}
|
||||
serviceUrl =
|
||||
ConfigurationManager.getInstance().readString(IServiceAPI.URL_KEY, "http://www.diy-fever.com/diylc/api/v1");
|
||||
ProxyFactory factory = new ProxyFactory(new PhpFlatProxy());
|
||||
service = factory.createProxy(IAnnouncementService.class, serviceUrl);
|
||||
}
|
||||
|
||||
private String getUserId() {
|
||||
String userId = ConfigurationManager.getInstance().readString(USER_ID_KEY, null);
|
||||
if (userId == null) {
|
||||
userId = UUID.randomUUID().toString();
|
||||
ConfigurationManager.getInstance().writeValue(USER_ID_KEY, userId);
|
||||
}
|
||||
return userId;
|
||||
}
|
||||
|
||||
public String getCurrentAnnouncements(boolean forceLast) throws ParseException {
|
||||
announcements = service.getAnnouncements(getUserId());
|
||||
if (announcements == null)
|
||||
return null;
|
||||
boolean hasUnread = false;
|
||||
StringBuilder sb = new StringBuilder("<html>");
|
||||
for (int i = 0; i < announcements.size(); i++) {
|
||||
Date date = dateFormat.parse(announcements.get(i).getDate());
|
||||
if (lastDate == null || lastDate.before(date) || lastDate.equals(date) || (forceLast && i == announcements.size() - 1)) {
|
||||
sb.append("<font size='4'><b>").append(announcements.get(i).getTitle()).append("</b> on ")
|
||||
.append(announcements.get(i).getDate()).append("</font>").append("<p>")
|
||||
.append(announcements.get(i).getText()).append("</p>");
|
||||
hasUnread = true;
|
||||
}
|
||||
}
|
||||
if (!hasUnread)
|
||||
return "";
|
||||
sb.append("</html>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void dismissed() {
|
||||
Date date = new Date();
|
||||
ConfigurationManager.getInstance().writeValue(LAST_READ_KEY, dateFormat.format(date));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.List;
|
||||
import com.diyfever.httpproxy.ParamName;
|
||||
|
||||
public interface IAnnouncementService {
|
||||
|
||||
public List<Announcement> getAnnouncements(@ParamName("userId")String userId);
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.clipboard;
|
||||
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Represents component selection as a {@link List} of {@link IDIYComponent} objects. Implements
|
||||
* {@link Transferable}, so it is suitable for clipboard usage.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ComponentTransferable implements Transferable, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static final DataFlavor listFlavor = new DataFlavor(ComponentTransferable.class, "application/diylc");
|
||||
|
||||
private List<IDIYComponent<?>> components;
|
||||
private Set<Set<IDIYComponent<?>>> groups;
|
||||
|
||||
public ComponentTransferable() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ComponentTransferable(List<IDIYComponent<?>> components) {
|
||||
super();
|
||||
this.components = components;
|
||||
this.groups = null;
|
||||
}
|
||||
|
||||
public ComponentTransferable(List<IDIYComponent<?>> components, Set<Set<IDIYComponent<?>>> groups) {
|
||||
super();
|
||||
this.components = components;
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
|
||||
if (flavor.equals(listFlavor)) {
|
||||
return this;
|
||||
}
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
return new DataFlavor[] {listFlavor};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
return flavor.equals(listFlavor);
|
||||
}
|
||||
|
||||
public List<IDIYComponent<?>> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public Set<Set<IDIYComponent<?>>> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 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.clipboard;
|
||||
|
||||
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.IDIYComponent;
|
||||
|
||||
public class ComponentTransferableFactory {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ComponentTransferableFactory.class);
|
||||
|
||||
private static ComponentTransferableFactory instance;
|
||||
|
||||
public static ComponentTransferableFactory getInstance() {
|
||||
if (instance == null)
|
||||
instance = new ComponentTransferableFactory();
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ComponentTransferable build(Collection<IDIYComponent<?>> selectedComponents, Set<Set<IDIYComponent<?>>> groups) {
|
||||
Set<IDIYComponent<?>> originalComponentSet = new HashSet<IDIYComponent<?>>(selectedComponents);
|
||||
List<IDIYComponent<?>> originalComponents = new ArrayList<IDIYComponent<?>>(selectedComponents);
|
||||
List<IDIYComponent<?>> clonedComponents = originalComponents.stream(
|
||||
).map(x -> {
|
||||
try {
|
||||
return x.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
LOG.error(e);
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public class BadPositionException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.Collection;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class BuildingBlock {
|
||||
|
||||
private String name;
|
||||
private Collection<IDIYComponent<?>> components;
|
||||
|
||||
public BuildingBlock(String name, Collection<IDIYComponent<?>> components) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Collection<IDIYComponent<?>> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
public void setComponents(Collection<IDIYComponent<?>> components) {
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.List;
|
||||
import java.util.Map;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class BuildingBlockPackage {
|
||||
|
||||
private Map<String, List<IDIYComponent<?>>> block;
|
||||
private String owner;
|
||||
|
||||
public BuildingBlockPackage() {
|
||||
}
|
||||
|
||||
public BuildingBlockPackage(Map<String, List<IDIYComponent<?>>> blocks, String owner) {
|
||||
super();
|
||||
this.block = blocks;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Map<String, List<IDIYComponent<?>>> getBlocks() {
|
||||
return block;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 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.util.List;
|
||||
import javax.swing.Icon;
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.annotations.BomPolicy;
|
||||
import org.diylc.core.annotations.KeywordPolicy;
|
||||
|
||||
/**
|
||||
* Entity class used to describe a component type.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @see IDIYComponent
|
||||
*/
|
||||
public class ComponentType implements Serializable {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private CreationMethod creationMethod;
|
||||
private String category;
|
||||
private String namePrefix;
|
||||
private String author;
|
||||
private Icon icon;
|
||||
private Class<? extends IDIYComponent<?>> instanceClass;
|
||||
private double zOrder;
|
||||
private boolean flexibleZOrder;
|
||||
private BomPolicy bomPolicy;
|
||||
private boolean autoEdit;
|
||||
private IComponentTransformer transformer;
|
||||
private KeywordPolicy keywordPolicy;
|
||||
private String keywordTag;
|
||||
private boolean enableCache;
|
||||
private List<String[]> datasheet;
|
||||
private int datasheetCreationStepCount;
|
||||
|
||||
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,
|
||||
int datasheetCreationStepCount) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.creationMethod = creationMethod;
|
||||
this.category = category;
|
||||
this.namePrefix = namePrefix;
|
||||
this.author = author;
|
||||
this.icon = icon;
|
||||
this.instanceClass = instanceClass;
|
||||
this.zOrder = zOrder;
|
||||
this.flexibleZOrder = flexibleZOrder;
|
||||
this.bomPolicy = bomPolicy;
|
||||
this.autoEdit = autoEdit;
|
||||
this.transformer = transformer;
|
||||
this.keywordPolicy = keywordPolicy;
|
||||
this.keywordTag = keywordTag;
|
||||
this.enableCache = enableCache;
|
||||
this.datasheet = datasheet;
|
||||
this.datasheetCreationStepCount = datasheetCreationStepCount;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public CreationMethod getCreationMethod() {
|
||||
return creationMethod;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public String getNamePrefix() {
|
||||
return namePrefix;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public Class<? extends IDIYComponent<?>> getInstanceClass() {
|
||||
return instanceClass;
|
||||
}
|
||||
|
||||
public double getZOrder() {
|
||||
return zOrder;
|
||||
}
|
||||
|
||||
public boolean isFlexibleZOrder() {
|
||||
return flexibleZOrder;
|
||||
}
|
||||
|
||||
public BomPolicy getBomPolicy() {
|
||||
return bomPolicy;
|
||||
}
|
||||
|
||||
public boolean isAutoEdit() {
|
||||
return autoEdit;
|
||||
}
|
||||
|
||||
public IComponentTransformer getTransformer() {
|
||||
return transformer;
|
||||
}
|
||||
|
||||
public KeywordPolicy getKeywordPolicy() {
|
||||
return keywordPolicy;
|
||||
}
|
||||
|
||||
public String getKeywordTag() {
|
||||
return keywordTag;
|
||||
}
|
||||
|
||||
public boolean getEnableCache() {
|
||||
return enableCache;
|
||||
}
|
||||
|
||||
public List<String[]> getDatasheet() {
|
||||
return datasheet;
|
||||
}
|
||||
|
||||
public int getDatasheetCreationStepCount() {
|
||||
return datasheetCreationStepCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package org.diylc.common;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.List;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.core.Angle;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.presenter.ComponentProcessor;
|
||||
|
||||
public class DefaultComponentTransformer implements IComponentTransformer {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(DefaultComponentTransformer.class);
|
||||
|
||||
@Override
|
||||
public boolean canRotate(IDIYComponent<?> component) {
|
||||
List<PropertyWrapper> properties =
|
||||
ComponentProcessor.getInstance().extractProperties(component.getClass());
|
||||
|
||||
for (PropertyWrapper property : properties) {
|
||||
if (property.getType().isAssignableFrom(Orientation.class)
|
||||
|| property.getType().isAssignableFrom(OrientationHV.class)
|
||||
|| property.getType().isAssignableFrom(Angle.class))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMirror(IDIYComponent<?> component) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mirroringChangesCircuit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
boolean canRotate = false;
|
||||
List<PropertyWrapper> properties =
|
||||
ComponentProcessor.getInstance().extractProperties(component.getClass());
|
||||
|
||||
for (PropertyWrapper property : properties) {
|
||||
try {
|
||||
property.readFrom(component);
|
||||
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException
|
||||
| SecurityException | NoSuchMethodException e) {
|
||||
LOG.warn("Error while rotating component " + component.getName(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
if (property.getType().isAssignableFrom(Orientation.class)) {
|
||||
canRotate = true;
|
||||
|
||||
Orientation o = (Orientation) property.getValue();
|
||||
int oValue = o.ordinal();
|
||||
oValue += direction;
|
||||
if (oValue < 0)
|
||||
oValue = Orientation.values().length - 1;
|
||||
if (oValue >= Orientation.values().length)
|
||||
oValue = 0;
|
||||
o = Orientation.values()[oValue];
|
||||
property.setValue(o);
|
||||
}
|
||||
|
||||
if (property.getType().isAssignableFrom(OrientationHV.class)) {
|
||||
canRotate = true;
|
||||
|
||||
OrientationHV o = (OrientationHV) property.getValue();
|
||||
int oValue = o.ordinal();
|
||||
oValue += direction;
|
||||
if (oValue < 0)
|
||||
oValue = OrientationHV.values().length - 1;
|
||||
if (oValue >= OrientationHV.values().length)
|
||||
oValue = 0;
|
||||
o = OrientationHV.values()[oValue];
|
||||
property.setValue(o);
|
||||
}
|
||||
|
||||
if (property.getType().isAssignableFrom(Angle.class)) {
|
||||
canRotate = true;
|
||||
|
||||
Angle angle = (Angle) property.getValue();
|
||||
Angle newAngle = angle.rotate(direction);
|
||||
property.setValue(newAngle);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.warn("Error while rotating component " + component.getName(), e);
|
||||
}
|
||||
|
||||
if (canRotate) {
|
||||
AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2 * direction,
|
||||
center.getX(), center.getY());
|
||||
for (int index = 0; index < component.getControlPointCount(); index++) {
|
||||
Point2D p = new Point2D.Double();
|
||||
rotate.transform(component.getControlPoint(index), p);
|
||||
component.setControlPoint(p, index);
|
||||
}
|
||||
|
||||
try {
|
||||
property.writeTo(component);
|
||||
} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException
|
||||
| SecurityException | NoSuchMethodException e) {
|
||||
LOG.warn("Error while rotating component " + component.getName(), e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mirror(IDIYComponent<?> component, Point2D center, int direction) {}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum Display {
|
||||
|
||||
NAME, VALUE, NONE, BOTH;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.Graphics;
|
||||
|
||||
/**
|
||||
* Enumerates all options that can be used when drawing a project.
|
||||
*
|
||||
* @see IPlugInPort#draw(java.awt.Graphics2D, java.util.Set, IComponentFiler)
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum DrawOption {
|
||||
|
||||
/**
|
||||
* Selection rectangle will be drawn when needed and selected components may be rendered
|
||||
* differently.
|
||||
*/
|
||||
SELECTION,
|
||||
/**
|
||||
* Selected zoom level will be applied to scale the {@link Graphics} before drawing.
|
||||
*/
|
||||
ZOOM,
|
||||
/**
|
||||
* Grid lines are drawn.
|
||||
*/
|
||||
GRID,
|
||||
/**
|
||||
* Control points are drawn.
|
||||
*/
|
||||
CONTROL_POINTS,
|
||||
/**
|
||||
* Anti-aliasing is used when drawing.
|
||||
*/
|
||||
ANTIALIASING,
|
||||
/**
|
||||
* Draw components in outline mode.
|
||||
*/
|
||||
OUTLINE_MODE,
|
||||
/**
|
||||
* Include extra space around the layout.
|
||||
*/
|
||||
EXTRA_SPACE,
|
||||
/**
|
||||
* Whether components should be cached or not.
|
||||
*/
|
||||
ENABLE_CACHING,
|
||||
/**
|
||||
* Whether locked components should be rendered as transparent or not.
|
||||
*/
|
||||
LOCKED_ALPHA;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.Rectangle;
|
||||
import java.awt.geom.Point2D;
|
||||
import org.diylc.core.Project;
|
||||
|
||||
/**
|
||||
* Enumerates all possible events between {@link IPlugInPort} and {@link IPlugIn}. Some events
|
||||
* overlap so be careful which ones you subscribe for and how you process them.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum EventType {
|
||||
|
||||
/**
|
||||
* Called when zoom level changes. Typically only one parameter of type {@link Double} is passed
|
||||
* with new zoom level.
|
||||
*/
|
||||
ZOOM_CHANGED,
|
||||
/**
|
||||
* Called when a new project is loaded. New {@link Project} is the first parameter. Boolean flag
|
||||
* is the second parameter and it's true when new project is loaded, false when the same project
|
||||
* has been either reloaded or loaded with undo/redo operations.
|
||||
*/
|
||||
PROJECT_LOADED,
|
||||
/**
|
||||
* Called when either current file name or modified flag are changed. The first parameter is the
|
||||
* current file name, the second one is a boolean modified flag.
|
||||
*/
|
||||
FILE_STATUS_CHANGED,
|
||||
/**
|
||||
* 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,
|
||||
/**
|
||||
* Called when selection size changes, together with a {@link Point2D} object containing selection
|
||||
* size (x = width, y = height). Size is expressed in the default measure (cm for metric, inches
|
||||
* for imperial).
|
||||
*/
|
||||
REPAINT,
|
||||
/**
|
||||
* Called when new component slot has been changed. The only parameter is {@link ComponentType}
|
||||
* and may be null.
|
||||
*/
|
||||
SLOT_CHANGED,
|
||||
/**
|
||||
* Called when the current project has been modified. Two instances of {@link Project} are passed
|
||||
* as parameters, one before and one after the change. The third parameter is a string containing
|
||||
* change description.
|
||||
*/
|
||||
PROJECT_MODIFIED,
|
||||
/**
|
||||
* Called when control points under the cursor are changed. A single parameter is passed, an
|
||||
* instance of <code>Map<IDIYComponent<?>, Set<Integer>></code> containing all the components and
|
||||
* indices of their control points that are under the cursor.
|
||||
*/
|
||||
AVAILABLE_CTRL_POINTS_CHANGED,
|
||||
/**
|
||||
* Called when mouse cursor is moved. Point object is passed, containing the current cursor
|
||||
* location (not taking zoom into account) in pixels and two {@link Point2D} objects with coordinates in
|
||||
* inches and mm
|
||||
*/
|
||||
MOUSE_MOVED,
|
||||
/**
|
||||
* Called when a layer status is changed. The first parameter is a set of indices of locked
|
||||
* layers. All layers not included are considered unlocked.
|
||||
*/
|
||||
LAYER_STATE_CHANGED,
|
||||
/**
|
||||
* Called when a layer visibility is changed. The first parameter is a set of indices of hidden
|
||||
* layers. All layers not included are considered visible.
|
||||
*/
|
||||
LAYER_VISIBILITY_CHANGED,
|
||||
/**
|
||||
* Called to update the status message. New status message is passed as a first parameter.
|
||||
*/
|
||||
STATUS_MESSAGE_CHANGED,
|
||||
/**
|
||||
* Signals the listeners to scroll to selection.
|
||||
*/
|
||||
SCROLL_TO;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public class Favorite implements Serializable, Comparable<Favorite> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private FavoriteType type;
|
||||
private String name;
|
||||
|
||||
public Favorite(FavoriteType type, String name) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public FavoriteType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((type == null) ? 0 : type.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;
|
||||
Favorite other = (Favorite) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (type != other.type)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type + ":" + name;
|
||||
}
|
||||
|
||||
public enum FavoriteType {
|
||||
Component, Block
|
||||
}
|
||||
|
||||
public String toDisplay() {
|
||||
String[] parts = name.split("\\.");
|
||||
return parts[parts.length - 1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Favorite o) {
|
||||
return toDisplay().compareToIgnoreCase(o.toDisplay());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum GridType {
|
||||
|
||||
LINES, CROSSHAIR, DOT, NONE;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum HorizontalAlignment {
|
||||
LEFT, CENTER, RIGHT;
|
||||
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.IOException;
|
||||
|
||||
public interface IBlockProcessor {
|
||||
|
||||
public static final String BLOCKS_KEY = "buildingBlocks";
|
||||
public static final String DEFAULT_BLOCKS_IMPORTED_KEY = "defaultBlocksImported";
|
||||
|
||||
void saveSelectionAsBlock(String blockName);
|
||||
|
||||
void loadBlock(String blockName) throws InvalidBlockException;
|
||||
|
||||
void deleteBlock(String blockName);
|
||||
|
||||
int importBlocks(String fileName) throws IOException;
|
||||
|
||||
public class BlockAlreadyExistsException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
|
||||
public class InvalidBlockException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 org.diylc.core.IDIYComponent;
|
||||
|
||||
public interface IComponentFilter {
|
||||
|
||||
boolean testComponent(IDIYComponent<?> component);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.geom.Point2D;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public interface IComponentTransformer {
|
||||
|
||||
public static final int CLOCKWISE = 1;
|
||||
public static final int COUNTER_CLOCKWISE = 1;
|
||||
|
||||
public static final int HORIZONTAL = 0;
|
||||
public static final int VERTICAL = 1;
|
||||
|
||||
boolean canRotate(IDIYComponent<?> component);
|
||||
|
||||
boolean canMirror(IDIYComponent<?> component);
|
||||
|
||||
boolean mirroringChangesCircuit();
|
||||
|
||||
void rotate(IDIYComponent<?> component, Point2D center, int direction);
|
||||
|
||||
void mirror(IDIYComponent<?> component, Point2D center, int direction);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public interface IKeyProcessor {
|
||||
|
||||
public static final int VK_LEFT = 0x25;
|
||||
public static final int VK_UP = 0x26;
|
||||
public static final int VK_RIGHT = 0x27;
|
||||
public static final int VK_DOWN = 0x28;
|
||||
public static final int VK_H = 0x48;
|
||||
public static final int VK_V = 0x56;
|
||||
|
||||
/**
|
||||
* Notifies the presenter that a key hes been pressed on the canvas.
|
||||
*
|
||||
* @param key
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
* @param altDown
|
||||
*
|
||||
* @return true if the event should be consumed
|
||||
*/
|
||||
boolean keyPressed(int key, boolean ctrlDown, boolean shiftDown, boolean altDown);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.Point;
|
||||
|
||||
public interface IMouseProcessor {
|
||||
|
||||
/**
|
||||
* Notifies the presenter that mouse is clicked.
|
||||
*
|
||||
* Note: point coordinates are display based, i.e. scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @param button
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
* @param altDown
|
||||
* @param clickCount
|
||||
*/
|
||||
void mouseClicked(Point point, int button, boolean ctrlDown, boolean shiftDown, boolean altDown, int clickCount);
|
||||
|
||||
/**
|
||||
* Notifies the presenter that mouse is moved.
|
||||
*
|
||||
* Note: point coordinates are display based, i.e. scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @param ctrlDown
|
||||
* @param shiftDown
|
||||
* @param altDown
|
||||
*/
|
||||
void mouseMoved(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown);
|
||||
|
||||
/**
|
||||
* Notification that drag has been started from the specified point.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @param dragAction
|
||||
* @param forceSelectionRect
|
||||
*/
|
||||
void dragStarted(Point point, int dragAction, boolean forceSelectionRect);
|
||||
|
||||
/**
|
||||
* Checks if it's possible to drop over the specified point.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
* @return
|
||||
*/
|
||||
boolean dragOver(Point point);
|
||||
|
||||
/**
|
||||
* Changes the current drag action during the dragging.
|
||||
*
|
||||
* @param dragAction
|
||||
*/
|
||||
void dragActionChanged(int dragAction);
|
||||
|
||||
/**
|
||||
* Notification that drag has been ended in the specified point.
|
||||
*
|
||||
* Note: point coordinates are scaled for zoom factor.
|
||||
*
|
||||
* @param point
|
||||
*/
|
||||
void dragEnded(Point point);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.List;
|
||||
import org.diylc.netlist.Netlist;
|
||||
import org.diylc.netlist.Node;
|
||||
import org.diylc.netlist.Summary;
|
||||
import org.diylc.netlist.TreeException;
|
||||
|
||||
public interface INetlistAnalyzer {
|
||||
|
||||
/**
|
||||
* @return summarizer name
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* @return summarizer short name
|
||||
*/
|
||||
String getShortName();
|
||||
|
||||
/**
|
||||
* @return name of the icon to use
|
||||
*/
|
||||
String getIconName();
|
||||
|
||||
/**
|
||||
* Summarizes all {@link Netlist}s provided.
|
||||
*
|
||||
* @param netlists
|
||||
* @param preferredOutput optional, needed only where there's more than one possible output node.
|
||||
* @return
|
||||
* @throws TreeException
|
||||
*/
|
||||
List<Summary> summarize(List<Netlist> netlists, Node preferredOutput) throws TreeException;
|
||||
|
||||
/**
|
||||
* @return name of the font to be used for display.
|
||||
*/
|
||||
String getFontName();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.List;
|
||||
import org.diylc.netlist.INetlistParser;
|
||||
import org.diylc.netlist.Netlist;
|
||||
import org.diylc.netlist.NetlistException;
|
||||
|
||||
/**
|
||||
* Interface for {@link Netlist} related operations.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface INetlistProcessor {
|
||||
|
||||
/**
|
||||
* Finds all {@link Netlist}s for each switch position combination.
|
||||
*
|
||||
* @param includeSwitches
|
||||
* @return
|
||||
* @throws NetlistException
|
||||
*/
|
||||
List<Netlist> extractNetlists(boolean includeSwitches) throws NetlistException;
|
||||
|
||||
/**
|
||||
* Finds all available {@link INetlistAnalyzer} implementations.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<INetlistAnalyzer> getNetlistAnalyzers();
|
||||
|
||||
/**
|
||||
* Finds all available {@link INetlistParser} implementations.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<INetlistParser> getNetlistParserDefinitions();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 org.diylc.appframework.simplemq.IMessageListener;
|
||||
|
||||
/**
|
||||
* Interface for plug-ins.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IPlugIn extends IMessageListener<EventType> {
|
||||
|
||||
/**
|
||||
* Method that connects the plug-in with {@link IPlugInPort}. Called by the application when
|
||||
* plug-in is installed.
|
||||
*
|
||||
* @param plugInPort
|
||||
*/
|
||||
void connect(IPlugInPort plugInPort);
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.Cursor;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.diylc.appframework.simplemq.IMessageListener;
|
||||
import org.diylc.appframework.simplemq.MessageDispatcher;
|
||||
import org.diylc.appframework.update.Version;
|
||||
import org.diylc.appframework.update.VersionNumber;
|
||||
import org.diylc.clipboard.ComponentTransferable;
|
||||
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.Size;
|
||||
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
|
||||
* @see EventType
|
||||
*/
|
||||
public interface IPlugInPort extends ISelectionProcessor, IMouseProcessor, IKeyProcessor, IVariantProcessor,
|
||||
IBlockProcessor, INetlistProcessor, ITestProcessor {
|
||||
|
||||
public static final String ANTI_ALIASING_KEY = "antiAliasing";
|
||||
public static final String HI_QUALITY_RENDER_KEY = "hiQualityRender";
|
||||
public static final String EXPORT_GRID_KEY = "exportGrid";
|
||||
public static final String STICKY_POINTS_KEY = "stickyPoints";
|
||||
public static final String METRIC_KEY = "metric";
|
||||
|
||||
public static final String SNAP_TO_KEY = "snapTo";
|
||||
public static final String CONTINUOUS_CREATION_KEY = "continuousCreation";
|
||||
public static final String AUTO_EDIT_KEY = "autoEdit";
|
||||
// public static final String ABNORMAL_EXIT_KEY = "abnormalExit";
|
||||
public static final String HEARTBEAT = "heartbeat";
|
||||
public static final String WHEEL_ZOOM_KEY = "wheelZoom";
|
||||
public static final String OUTLINE_KEY = "outline";
|
||||
public static final String THEME_KEY = "theme";
|
||||
public static final String RECENT_COMPONENTS_KEY = "recentComponents";
|
||||
public static final String RECENT_FILES_KEY = "recentFiles";
|
||||
public static final String SHOW_RULERS_KEY = "showRulers";
|
||||
public static final String SHOW_GRID_KEY = "showGrid";
|
||||
public static final String HIGHLIGHT_CONTINUITY_AREA = "highlightContinuityArea";
|
||||
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 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 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 LOCKED_ALPHA = "lockedAlpha";
|
||||
|
||||
public static final String LANGUAGE = "language";
|
||||
public static final String LANGUAGE_DEFAULT = "English";
|
||||
|
||||
public static final int DND_TOGGLE_STICKY = 0x1;
|
||||
public static final int DND_TOGGLE_SNAP = 0x40000000;
|
||||
|
||||
/**
|
||||
* Mouse button constants.
|
||||
*/
|
||||
public static final int NOBUTTON = 0;
|
||||
public static final int BUTTON1 = 1;
|
||||
public static final int BUTTON2 = 2;
|
||||
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
|
||||
* @param altDown
|
||||
* @return cursor
|
||||
*/
|
||||
Cursor getCursorAt(Point point, boolean ctrlDown, boolean shiftDown, boolean altDown);
|
||||
|
||||
/**
|
||||
* Returns an instance of currently loaded project.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Project getCurrentProject();
|
||||
|
||||
/**
|
||||
* Loads specified {@link Project}.
|
||||
*
|
||||
* @param project
|
||||
* @param freshStart
|
||||
* @param optional file name when loading from a file
|
||||
*/
|
||||
void loadProject(Project project, boolean freshStart, String filename);
|
||||
|
||||
/**
|
||||
* Creates a new project.
|
||||
*/
|
||||
void createNewProject();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void exportToGerber(String fileNameBase, Graphics2D g2d);
|
||||
|
||||
/**
|
||||
* @return the current file name.
|
||||
*/
|
||||
String getCurrentFileName();
|
||||
|
||||
/**
|
||||
* @return true if the current project is modified.
|
||||
*/
|
||||
boolean isProjectModified();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param externalZoom
|
||||
* @param scaleFactor
|
||||
* @param visibleRect
|
||||
*/
|
||||
void draw(Graphics2D g2d, Set<DrawOption> drawOptions, IComponentFilter filter, Double externalZoom, Double scaleFactor, Rectangle2D visibleRect);
|
||||
|
||||
Double[] getAvailableZoomLevels();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<Version> getRecentUpdates();
|
||||
|
||||
/**
|
||||
* Adds a list of components to the project.
|
||||
*
|
||||
* @param componentTransferable
|
||||
* @param autoGroup
|
||||
* @param assignNewNames
|
||||
*/
|
||||
void pasteComponents(ComponentTransferable componentTransferable, boolean autoGroup, boolean assignNewNames);
|
||||
|
||||
/**
|
||||
* Duplicates selected components and places them nearby.
|
||||
*/
|
||||
void duplicateSelection();
|
||||
|
||||
/**
|
||||
* Deletes all the selected components from the project.
|
||||
*/
|
||||
void deleteSelectedComponents();
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void setSelectionDefaultPropertyValue(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
void setDefaultPropertyValue(Class<?> clazz, String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* @return a list of properties that are mutual for all the selected components. Resulting list
|
||||
* may be empty if selected components do not have mutual properties or can be null if the
|
||||
* selection is empty.
|
||||
*/
|
||||
List<PropertyWrapper> getMutualSelectionProperties();
|
||||
|
||||
void editSelection();
|
||||
|
||||
/**
|
||||
* @return a list of editable properties of the current project.
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
List<PropertyWrapper> getProperties(Object obj);
|
||||
|
||||
/**
|
||||
* Applies specified properties to the current project.
|
||||
*
|
||||
* @param obj
|
||||
* @param properties
|
||||
*/
|
||||
void applyProperties(Object obj, List<PropertyWrapper> properties);
|
||||
|
||||
/**
|
||||
* Gets the current new component slot.
|
||||
*/
|
||||
ComponentType getNewComponentTypeSlot();
|
||||
|
||||
/**
|
||||
* Sets the new component slot. Specified component type will be used to instantiate new
|
||||
* component.
|
||||
*
|
||||
* @param componentType
|
||||
* @param template optional
|
||||
* @param model optional datasheet model
|
||||
* @param forceInstatiate
|
||||
*/
|
||||
void setNewComponentTypeSlot(ComponentType componentType, Template template, String[] model, boolean forceInstatiate);
|
||||
|
||||
/**
|
||||
* Locks or unlocks the specified layer. All components within +- 0.5 range will be affected by
|
||||
* the change as well.
|
||||
*
|
||||
* @param layerZOrder
|
||||
* @param locked
|
||||
*/
|
||||
void setLayerLocked(int layerZOrder, boolean locked);
|
||||
|
||||
/**
|
||||
* Shows or hides the specified layer. All components within +- 0.5 range will be affected by the
|
||||
* change as well.
|
||||
*
|
||||
* @param layerZOrder
|
||||
* @param visible
|
||||
*/
|
||||
void setLayerVisibility(int layerZOrder, boolean visible);
|
||||
|
||||
/**
|
||||
* @return selection size expressed in both inches or centimeters, respectively
|
||||
*/
|
||||
Point2D[] calculateSelectionDimension();
|
||||
|
||||
// /**
|
||||
// * @return the smallest rectangle that encloses the selection
|
||||
// */
|
||||
// Rectangle2D getSelectedAreaRect();
|
||||
|
||||
/**
|
||||
* Causes the display to refresh.
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* @return currently selected theme.
|
||||
*/
|
||||
Theme getSelectedTheme();
|
||||
|
||||
/**
|
||||
* Changes the current theme.
|
||||
*
|
||||
* @param theme
|
||||
*/
|
||||
void setSelectedTheme(Theme theme);
|
||||
|
||||
/**
|
||||
* Renumbers all the selected components.
|
||||
*
|
||||
* @param xAxisFirst
|
||||
*/
|
||||
void renumberSelectedComponents(boolean xAxisFirst);
|
||||
|
||||
/**
|
||||
* @return size of extra space around the canvas
|
||||
*/
|
||||
double getExtraSpace();
|
||||
|
||||
/**
|
||||
* Applies changes to the current project as specified by the provided {@link IProjectEditor}.
|
||||
*
|
||||
* @param editor
|
||||
*/
|
||||
void applyEditor(IProjectEditor editor);
|
||||
|
||||
/**
|
||||
* Locks or unlocks a single component.
|
||||
*/
|
||||
void lockComponent(IDIYComponent<?> c, boolean locked);
|
||||
|
||||
/**
|
||||
* Checks for proximity between continuity areas and creates additional components around any problematic areas to visually identify them.
|
||||
*
|
||||
* @param threshold
|
||||
*/
|
||||
List<Area> checkContinuityAreaProximity(Size threshold);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
|
||||
public interface IProjectEditor {
|
||||
|
||||
Set<IDIYComponent<?>> edit(Project project, Set<IDIYComponent<?>> selection);
|
||||
|
||||
String getEditAction();
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import org.diylc.clipboard.ComponentTransferable;
|
||||
import org.diylc.core.ExpansionMode;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
public interface ISelectionProcessor {
|
||||
|
||||
/**
|
||||
* Returns the current {@link ComponentTransferable}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<IDIYComponent<?>> getSelectedComponents();
|
||||
|
||||
/**
|
||||
* Returns selected component types
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<ComponentType> getSelectedComponentTypes();
|
||||
|
||||
/**
|
||||
* Updates the selection with the specified list of component. Also, updates control point map
|
||||
* with all components that are stuck to the newly selected components.
|
||||
*
|
||||
* @param newSelection
|
||||
* @param panToSelection
|
||||
*/
|
||||
void setSelection(Collection<IDIYComponent<?>> newSelection, boolean panToSelection);
|
||||
|
||||
/**
|
||||
* Finds all components at the specified location, sorted by z-index from top to bottom. Location
|
||||
* depends on the current zoom level.
|
||||
*
|
||||
* @param point
|
||||
* @param includeLocked
|
||||
* @return
|
||||
*/
|
||||
List<IDIYComponent<?>> findComponentsAt(Point2D point, boolean includeLocked);
|
||||
|
||||
/**
|
||||
* Expands the current selection to include surrounding components. Options are controlled with
|
||||
* <code>expansionMode</code> flag.
|
||||
*
|
||||
* @param expansionMode
|
||||
*/
|
||||
void expandSelection(ExpansionMode expansionMode);
|
||||
|
||||
/**
|
||||
* Selects all components in the project.
|
||||
*
|
||||
* @param int layer if > 0, designates which layer to select. If <= 0 we should select all
|
||||
* regardless of layer
|
||||
*/
|
||||
void selectAll(int layer);
|
||||
|
||||
/**
|
||||
* Rotates selection for 90 degrees.
|
||||
*
|
||||
* @param direction 1 for clockwise, -1 for counter-clockwise
|
||||
*/
|
||||
void rotateSelection(int direction);
|
||||
|
||||
/**
|
||||
* Groups all selected components.
|
||||
*/
|
||||
void groupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Ungroups all selected components.
|
||||
*/
|
||||
void ungroupSelectedComponents();
|
||||
|
||||
/**
|
||||
* Mirrors selected components in the given axis.
|
||||
*
|
||||
* @param direction
|
||||
*/
|
||||
void mirrorSelection(int direction);
|
||||
|
||||
/**
|
||||
* Returns the minimum rectangle containing all selected components, or null if none exists.
|
||||
* Rectangle is scaled by the current zoom level.
|
||||
*
|
||||
* @param applyZoom
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Rectangle2D getSelectionBounds(boolean applyZoom);
|
||||
|
||||
/**
|
||||
* Moves selection for the specified offset.
|
||||
*
|
||||
* @param xOffset
|
||||
* @param yOffset
|
||||
* @param includeStuckComponents
|
||||
*/
|
||||
void nudgeSelection(Size xOffset, Size yOffset, boolean includeStuckComponents);
|
||||
|
||||
/**
|
||||
* Selects components that match the criteria.
|
||||
*
|
||||
* @param criteria
|
||||
*/
|
||||
void selectMatching(String criteria);
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to apply the specified model to all selected components.
|
||||
*
|
||||
* @param model
|
||||
*/
|
||||
void applyModelToSelection(String[] model);
|
||||
|
||||
/**
|
||||
* Sends each of the selected components one step back.
|
||||
*/
|
||||
void sendSelectionToBack();
|
||||
|
||||
/**
|
||||
* Brings each of the selected components one step to front.
|
||||
*/
|
||||
void bringSelectionToFront();
|
||||
|
||||
/**
|
||||
* Move selected components to z index starting from the provided value
|
||||
* @param zIndex
|
||||
*/
|
||||
void moveSelectionToZIndex(int zIndex);
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Abstract layer between the app and platform worker thread implementation.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public interface ITask<T> {
|
||||
|
||||
/**
|
||||
* Runs in background thread.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
T doInBackground() throws Exception;
|
||||
|
||||
/**
|
||||
* Called if background thread fails.
|
||||
*
|
||||
* @param e
|
||||
*/
|
||||
void failed(Exception e);
|
||||
|
||||
/**
|
||||
* Called if background thread is executed correctly, the result is passed as a parameter.
|
||||
*
|
||||
* @param result
|
||||
*/
|
||||
void complete(T result);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.IOException;
|
||||
import java.util.List;
|
||||
import org.diylc.core.Template;
|
||||
|
||||
public interface IVariantProcessor {
|
||||
|
||||
public static final String TEMPLATES_KEY = "templates";
|
||||
public static final String DEFAULT_TEMPLATES_KEY = "defaultTemplates";
|
||||
public static final String DEFAULT_TEMPLATES_IMPORT_DATE_KEY = "defaultTemplatesImportDate";
|
||||
|
||||
void saveSelectedComponentAsVariant(String variantName);
|
||||
|
||||
List<Template> getVariantsFor(ComponentType type);
|
||||
|
||||
List<Template> getVariantsForSelection();
|
||||
|
||||
void applyVariantToSelection(Template variant);
|
||||
|
||||
void deleteVariant(ComponentType type, String variantName);
|
||||
|
||||
void setDefaultVariant(ComponentType type, String variantName);
|
||||
|
||||
int importVariants(String fileName) throws IOException;
|
||||
|
||||
String getDefaultVariant(ComponentType type);
|
||||
|
||||
public class VariantAlreadyExistsException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum LabelPosition {
|
||||
|
||||
ABOVE, BELOW;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum LineStyle {
|
||||
|
||||
SOLID, DASHED, DOTTED;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 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.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Stroke;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Repository for object that may be reused, such as {@link Stroke} or {@link AlphaComposite}.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ObjectCache {
|
||||
|
||||
private static ObjectCache instance;
|
||||
|
||||
public static ObjectCache getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ObjectCache();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ObjectCache() {}
|
||||
|
||||
private Map<Float, Stroke> basicStrokeMap = new HashMap<Float, Stroke>();
|
||||
private Map<Float, Stroke> zoomableStrokeMap = new HashMap<Float, Stroke>();
|
||||
private Map<String, Stroke> dashStrokeMap = new HashMap<String, Stroke>();
|
||||
|
||||
public Stroke fetchBasicStroke(float width) {
|
||||
if (basicStrokeMap.containsKey(width)) {
|
||||
return basicStrokeMap.get(width);
|
||||
}
|
||||
Stroke stroke = new BasicStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
|
||||
basicStrokeMap.put(width, stroke);
|
||||
return stroke;
|
||||
}
|
||||
|
||||
public Stroke fetchZoomableStroke(float width) {
|
||||
if (zoomableStrokeMap.containsKey(width)) {
|
||||
return zoomableStrokeMap.get(width);
|
||||
}
|
||||
Stroke stroke = new ZoomableStroke(width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
|
||||
zoomableStrokeMap.put(width, stroke);
|
||||
return stroke;
|
||||
}
|
||||
|
||||
public Stroke fetchStroke(float width, float[] dash, float phase, int cap) {
|
||||
String key = width + "|" + Arrays.toString(dash) + "|" + phase + "|" + cap;
|
||||
if (dashStrokeMap.containsKey(key)) {
|
||||
return dashStrokeMap.get(key);
|
||||
}
|
||||
Stroke stroke = new BasicStroke(width, cap, BasicStroke.JOIN_ROUND, 0, dash, phase);
|
||||
dashStrokeMap.put(key, stroke);
|
||||
return stroke;
|
||||
}
|
||||
|
||||
public Stroke fetchStroke(float width, int cap) {
|
||||
String key = width + "|" + cap;
|
||||
if (dashStrokeMap.containsKey(key)) {
|
||||
return dashStrokeMap.get(key);
|
||||
}
|
||||
Stroke stroke = new BasicStroke(width, cap, BasicStroke.JOIN_ROUND);
|
||||
dashStrokeMap.put(key, stroke);
|
||||
return stroke;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum Orientation {
|
||||
|
||||
DEFAULT, _90, _180, _270;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (this == DEFAULT) {
|
||||
return "Default";
|
||||
} else {
|
||||
return name().replace("_", "") + " degrees clockwise";
|
||||
}
|
||||
}
|
||||
|
||||
public double toDegrees() {
|
||||
switch (this) {
|
||||
case DEFAULT:
|
||||
return 0;
|
||||
case _180:
|
||||
return 180;
|
||||
case _270:
|
||||
return 270;
|
||||
case _90:
|
||||
return 90;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public double toRadians() {
|
||||
return Math.toRadians(toDegrees());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum OrientationHV {
|
||||
|
||||
VERTICAL, HORIZONTAL;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 org.diylc.core.gerber.GerberLayer;
|
||||
|
||||
public enum PCBLayer {
|
||||
|
||||
_1("Bottom"), _2("Top"), _3("Inner 1"), _4("Inner 2"), _5("Inner 3"), _6("Inner 4"), _7("Inner 5"), _8("Inner 6");
|
||||
|
||||
private String label;
|
||||
|
||||
private PCBLayer(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return label;
|
||||
};
|
||||
|
||||
public int getId() {
|
||||
return this.ordinal() + 1;
|
||||
}
|
||||
|
||||
public GerberLayer toGerberCopperLayer() {
|
||||
switch (this) {
|
||||
case _1: return GerberLayer.CopperBot;
|
||||
case _2: return GerberLayer.CopperTop;
|
||||
default:
|
||||
throw new RuntimeException("Unsupported PCB layer: " + this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
|
||||
/**
|
||||
* Entity class for editable properties extracted from component objects. Represents a single
|
||||
* editable property together with it's current value.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class PropertyWrapper implements Cloneable {
|
||||
|
||||
private String name;
|
||||
private Class<?> type;
|
||||
private Object value;
|
||||
private String setter;
|
||||
private String getter;
|
||||
private boolean defaultable;
|
||||
private IPropertyValidator validator;
|
||||
private boolean unique = true;
|
||||
private boolean changed = false;
|
||||
private int sortOrder;
|
||||
private Object ownerObject;
|
||||
|
||||
public PropertyWrapper(String name, Class<?> type, String getter, String setter, boolean defaultable,
|
||||
IPropertyValidator validator, int sortOrder) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
this.defaultable = defaultable;
|
||||
this.validator = validator;
|
||||
this.sortOrder = sortOrder;
|
||||
this.ownerObject = null;
|
||||
}
|
||||
|
||||
public void readFrom(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException, SecurityException, NoSuchMethodException {
|
||||
this.ownerObject = object;
|
||||
this.value = getGetter().invoke(object);
|
||||
}
|
||||
|
||||
// public void readUniqueFrom(IDIYComponent component)
|
||||
// throws IllegalArgumentException, IllegalAccessException,
|
||||
// InvocationTargetException {
|
||||
// Object newValue = getter.invoke(component);
|
||||
// if (!newValue.equals(value)) {
|
||||
// this.value = null;
|
||||
// }
|
||||
// }
|
||||
|
||||
public void writeTo(Object object) throws IllegalArgumentException, IllegalAccessException,
|
||||
InvocationTargetException, SecurityException, NoSuchMethodException {
|
||||
// nothing to do if no setter
|
||||
if (setter == null)
|
||||
return;
|
||||
object.getClass().getMethod(setter, type).invoke(object, this.value);
|
||||
}
|
||||
|
||||
public Method getGetter() throws SecurityException, NoSuchMethodException {
|
||||
return getOwnerObject().getClass().getMethod(getter);
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return setter == null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Object getOwnerObject() {
|
||||
return ownerObject;
|
||||
}
|
||||
|
||||
public boolean isDefaultable() {
|
||||
return defaultable;
|
||||
}
|
||||
|
||||
public IPropertyValidator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
public void setUnique(boolean unique) {
|
||||
this.unique = unique;
|
||||
}
|
||||
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
public void setChanged(boolean changed) {
|
||||
this.changed = changed;
|
||||
}
|
||||
|
||||
public int getSortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Object clone() throws CloneNotSupportedException {
|
||||
// // Try to invoke clone method on value if possible.
|
||||
// try {
|
||||
// Method cloneMethod = value.getClass().getMethod("clone");
|
||||
// return new Property(name, type, cloneMethod.invoke(value));
|
||||
// } catch (Exception e) {
|
||||
// }
|
||||
// return new Property(name, type, value);
|
||||
// }
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
PropertyWrapper clone =
|
||||
new PropertyWrapper(this.name, this.type, this.getter, this.setter, this.defaultable, this.validator,
|
||||
this.sortOrder);
|
||||
clone.value = this.value;
|
||||
clone.changed = this.changed;
|
||||
clone.unique = this.unique;
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (defaultable ? 1231 : 1237);
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((setter == null) ? 0 : setter.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;
|
||||
PropertyWrapper other = (PropertyWrapper) obj;
|
||||
if (defaultable != other.defaultable)
|
||||
return false;
|
||||
if (getter == null) {
|
||||
if (other.getter != null)
|
||||
return false;
|
||||
} else if (!getter.equals(other.getter))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (setter == null) {
|
||||
if (other.setter != null)
|
||||
return false;
|
||||
} else if (!setter.equals(other.setter))
|
||||
return false;
|
||||
if (type == null) {
|
||||
if (other.type != null)
|
||||
return false;
|
||||
} else if (!type.equals(other.type))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + " = " + value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum ResistorColorCode {
|
||||
|
||||
NONE, _4_BAND, _5_BAND;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (name().startsWith("_")) {
|
||||
return name().substring(1).replace("_", " ").toLowerCase();
|
||||
}
|
||||
return name().substring(0, 1).toUpperCase() + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.List;
|
||||
import java.util.Map;
|
||||
import org.diylc.core.Template;
|
||||
|
||||
public class VariantPackage {
|
||||
|
||||
private Map<String, List<Template>> variants;
|
||||
private String owner;
|
||||
|
||||
public VariantPackage() {
|
||||
}
|
||||
|
||||
public VariantPackage(Map<String, List<Template>> variants, String owner) {
|
||||
super();
|
||||
this.variants = variants;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Map<String, List<Template>> getVariants() {
|
||||
return variants;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum VerticalAlignment {
|
||||
TOP, CENTER, BOTTOM;
|
||||
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.awt.BasicStroke;
|
||||
|
||||
/***
|
||||
* {@link BasicStroke} that will always be zoomed in when rendered.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ZoomableStroke extends BasicStroke {
|
||||
|
||||
public ZoomableStroke() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public ZoomableStroke(float width) {
|
||||
super(width);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public ZoomableStroke(float width, int cap, int join) {
|
||||
super(width, cap, join);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public ZoomableStroke(float width, int cap, int join, float miterlimit) {
|
||||
super(width, cap, join, miterlimit);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public ZoomableStroke(float width, int cap, int join, float miterlimit, float[] dash, float dash_phase) {
|
||||
super(width, cap, join, miterlimit, dash, dash_phase);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.Shape;
|
||||
import org.diylc.common.Orientation;
|
||||
import org.diylc.core.Angle;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
public abstract class AbstractAngledComponent<T> extends AbstractTransparentComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Deprecated
|
||||
protected Orientation orientation;
|
||||
protected int angle;
|
||||
|
||||
transient protected Shape[] body;
|
||||
|
||||
protected abstract void updateControlPoints();
|
||||
|
||||
@EditableProperty
|
||||
@SuppressWarnings("incomplete-switch")
|
||||
public Angle getAngle() {
|
||||
if (orientation != null) {
|
||||
switch (orientation) {
|
||||
case _90:
|
||||
angle = 90;
|
||||
break;
|
||||
case _180:
|
||||
angle = 180;
|
||||
break;
|
||||
case _270:
|
||||
angle = 270;
|
||||
break;
|
||||
}
|
||||
orientation = null;
|
||||
}
|
||||
return Angle.of(angle);
|
||||
}
|
||||
|
||||
public void setAngle(Angle angle) {
|
||||
this.angle = angle.getValue();
|
||||
updateControlPoints();
|
||||
// Reset body shape
|
||||
body = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.Font;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
import org.diylc.core.measures.Size;
|
||||
|
||||
/**
|
||||
* Abstract implementation of {@link IDIYComponent} that contains component name and toString.
|
||||
*
|
||||
* IMPORTANT: to improve performance, all fields except for <code>Point</code> and
|
||||
* <code>Point</code> arrays should be immutable. Failing to comply with this can result in annoying
|
||||
* and hard to trace bugs.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractComponent<T> implements IDIYComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected String name = "";
|
||||
|
||||
public static Color SELECTION_COLOR = Color.red;
|
||||
public static Color LABEL_COLOR = Color.black;
|
||||
public static Color LABEL_COLOR_SELECTED = Color.red;
|
||||
public static Font LABEL_FONT = new Font("Square721 BT", Font.PLAIN, 14);
|
||||
public static Color METAL_COLOR = Color.decode("#759DAF");
|
||||
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 FR4_COLOR = Color.decode("#6B9B6B");
|
||||
public static Color FR4_LIGHT_COLOR = Color.decode("#BABE71");
|
||||
public static Color PHENOLIC_COLOR = Color.decode("#F8EBB3");
|
||||
public static Color PHENOLIC_DARK_COLOR = Color.decode("#CD8500");
|
||||
|
||||
@EditableProperty(defaultable = false)
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name == null ? "(null)" : name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValueForDisplay() {
|
||||
if (getValue() == null)
|
||||
return "";
|
||||
|
||||
Object val = getValue();
|
||||
if (val.getClass().isArray()) {
|
||||
return String.join(" / ", Arrays.stream((Object[])val).map(x -> x == null ? "" : x.toString()).collect(Collectors.toList()));
|
||||
}
|
||||
return val.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest odd number, i.e. x when x is odd, or x + 1 when x is even.
|
||||
*
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
protected int getClosestOdd(double x) {
|
||||
return ((int) x / 2) * 2 + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest odd number, i.e. x when x is odd, or x + 1 when x is even.
|
||||
*
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
protected int getClosestOdd(Size s) {
|
||||
double x = s.convertToPixels();
|
||||
return ((int) x / 2) * 2 + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns darker color if possible, or lighter if it's already dark
|
||||
*
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
protected Color darkerOrLighter(Color color) {
|
||||
float[] hsb = new float[3];
|
||||
Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb);
|
||||
return new Color(Color.HSBtoRGB(hsb[0], hsb[1], hsb[2] > 0.5 ? hsb[2] - 0.25f : hsb[2] + 0.25f));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clip
|
||||
* @return true if none of the control points lie in the clip rectangle.
|
||||
*/
|
||||
protected boolean checkPointsClipped(Shape clip) {
|
||||
if (clip == null) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < getControlPointCount(); i++) {
|
||||
if (clip.contains(getControlPoint(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
double minX = Integer.MAX_VALUE;
|
||||
double minY = Integer.MAX_VALUE;
|
||||
double maxX = Integer.MIN_VALUE;
|
||||
double maxY = Integer.MIN_VALUE;
|
||||
for (int i = 0; i < getControlPointCount(); i++) {
|
||||
Point2D p = getControlPoint(i);
|
||||
if (minX > p.getX()) {
|
||||
minX = p.getX();
|
||||
}
|
||||
if (maxX < p.getX()) {
|
||||
maxX = p.getX();
|
||||
}
|
||||
if (minY > p.getY()) {
|
||||
minY = p.getY();
|
||||
}
|
||||
if (maxY < p.getY()) {
|
||||
maxY = p.getY();
|
||||
}
|
||||
}
|
||||
Rectangle2D rect = new Rectangle2D.Double(minX, minY, maxX - minX, maxY - minY);
|
||||
return !clip.intersects(rect);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public IDIYComponent<T> clone() throws CloneNotSupportedException {
|
||||
try {
|
||||
// Instantiate object of the same type
|
||||
Class<?> clazz = this.getClass();
|
||||
AbstractComponent<T> newInstance = (AbstractComponent<T>) clazz.getDeclaredConstructor().newInstance();
|
||||
while (AbstractComponent.class.isAssignableFrom(clazz)) {
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
clazz = clazz.getSuperclass();
|
||||
// fields = this.getClass().getDeclaredFields();
|
||||
// Copy over all non-static, non-final fields that are declared
|
||||
// in AbstractComponent or one of it's child classes
|
||||
for (Field field : fields) {
|
||||
if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
Object value = field.get(this);
|
||||
|
||||
// Deep copy point arrays.
|
||||
// TODO: something nicer
|
||||
if (value != null && value.getClass().isArray()
|
||||
&& value.getClass().getComponentType().isAssignableFrom(Point2D.class)) {
|
||||
Object newArray = Array.newInstance(value.getClass().getComponentType(), Array.getLength(value));
|
||||
for (int i = 0; i < Array.getLength(value); i++) {
|
||||
Point2D p = (Point2D) Array.get(value, i);
|
||||
if (p != null)
|
||||
Array.set(newArray, i, new Point2D.Double(p.getX(), p.getY()));
|
||||
}
|
||||
value = newArray;
|
||||
}
|
||||
// Deep copy points.
|
||||
// TODO: something nicer
|
||||
if (value != null && value instanceof Point2D) {
|
||||
Point2D p = (Point2D) value;
|
||||
value = new Point2D.Double(p.getX(), p.getY());
|
||||
}
|
||||
|
||||
field.set(newInstance, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newInstance;
|
||||
} catch (Exception e) {
|
||||
throw new CloneNotSupportedException("Could not clone the component. Reason: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equalsTo(IDIYComponent<?> other) {
|
||||
if (other == null)
|
||||
return false;
|
||||
if (!other.getClass().equals(this.getClass()))
|
||||
return false;
|
||||
Class<?> clazz = this.getClass();
|
||||
while (AbstractComponent.class.isAssignableFrom(clazz)) {
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
clazz = clazz.getSuperclass();
|
||||
// fields = this.getClass().getDeclaredFields();
|
||||
// Copy over all non-static, non-final and non-transient fields that are declared
|
||||
// in
|
||||
// AbstractComponent or one of it's child classes
|
||||
for (Field field : fields) {
|
||||
if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) &&
|
||||
!Modifier.isTransient(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
Object value = field.get(this);
|
||||
Object otherValue = field.get(other);
|
||||
if (!compareObjects(value, otherValue))
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean compareObjects(Object o1, Object o2) {
|
||||
if (o1 == null && o2 == null)
|
||||
return true;
|
||||
if (o1 == null || o2 == null)
|
||||
return false;
|
||||
if (o1.getClass().isArray()) {
|
||||
if (o1.getClass().getComponentType() == byte.class)
|
||||
return Arrays.equals((byte[]) o1, (byte[]) o2);
|
||||
if (o1.getClass().getComponentType() == double.class)
|
||||
return Arrays.equals((double[]) o1, (double[]) o2);
|
||||
if (o1.getClass().getComponentType() == int.class)
|
||||
return Arrays.equals((int[]) o1, (int[]) o2);
|
||||
return Arrays.equals((Object[]) o1, (Object[]) o2);
|
||||
}
|
||||
return o1.equals(o2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getControlPointNodeName(int index) {
|
||||
return Integer.toString(index + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInternalLinkName(int index1, int index2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSectionNames(int pointIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPointMoveFreely(int pointIndex) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getCachingBounds() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createdIn(Project project) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 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.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.appframework.miscutils.ConfigurationManager;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.LineStyle;
|
||||
import org.diylc.common.ObjectCache;
|
||||
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;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
public abstract class AbstractCurvedComponent<T> extends AbstractTransparentComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(AbstractCurvedComponent.class);
|
||||
|
||||
public static Color GUIDELINE_COLOR = Color.blue;
|
||||
public static Size DEFAULT_SIZE = new Size(1d, SizeUnit.in);
|
||||
|
||||
// for backward compatibility
|
||||
protected Point2D[] controlPoints = null;
|
||||
|
||||
protected Point2D[] controlPoints2 = new Point2D[] {new Point2D.Double(0, 0),
|
||||
new Point2D.Double(DEFAULT_SIZE.convertToPixels() / 2, 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.FOUR;
|
||||
protected LineStyle style = LineStyle.SOLID;
|
||||
protected Boolean smooth = true;
|
||||
|
||||
private int lastUpdatePointIndex = -1;
|
||||
|
||||
/**
|
||||
* Draws the specified curve onto graphics.
|
||||
*
|
||||
* @param curve
|
||||
* @param g2d
|
||||
* @param componentState
|
||||
* @param theme
|
||||
*/
|
||||
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) {
|
||||
g2d.setColor(getDefaultColor().darker());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3));
|
||||
CubicCurve2D curve =
|
||||
new CubicCurve2D.Double(1, height - 1, width / 4, height / 3, 3 * width / 4, 2 * height / 3, width - 1, 1);
|
||||
g2d.draw(curve);
|
||||
g2d.setColor(getDefaultColor());
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.draw(curve);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||
IDrawingObserver drawingObserver) {
|
||||
if (checkPointsClipped(g2d.getClip())) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point2D[] p = getControlPoints();
|
||||
|
||||
// smoothen the curve if needed
|
||||
if (getSmooth() && lastUpdatePointIndex >= 0) {
|
||||
if (getPointCount() == PointCount.FIVE && (lastUpdatePointIndex == 1 || lastUpdatePointIndex == 2)) {
|
||||
p[3] = findThirdPoint(p[2], p[1]);
|
||||
}
|
||||
if (getPointCount() == PointCount.FIVE && lastUpdatePointIndex == 3) {
|
||||
p[1] = findThirdPoint(p[2], p[3]);
|
||||
}
|
||||
if (getPointCount() == PointCount.SEVEN && (lastUpdatePointIndex == 2 || lastUpdatePointIndex == 3)) {
|
||||
p[4] = findThirdPoint(p[3], p[2]);
|
||||
}
|
||||
if (getPointCount() == PointCount.SEVEN && lastUpdatePointIndex == 4) {
|
||||
p[2] = findThirdPoint(p[3], p[4]);
|
||||
}
|
||||
lastUpdatePointIndex = -1;
|
||||
}
|
||||
|
||||
if (componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING) {
|
||||
// Do not track guidelines.
|
||||
drawingObserver.stopTracking();
|
||||
g2d.setStroke(Constants.DASHED_STROKE);
|
||||
g2d.setColor(GUIDELINE_COLOR);
|
||||
for (int i = 0; i < p.length - 1; i++) {
|
||||
g2d.drawLine((int)p[i].getX(), (int)p[i].getY(), (int)p[i + 1].getX(), (int)p[i + 1].getY());
|
||||
}
|
||||
drawingObserver.startTracking();
|
||||
}
|
||||
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(p[0].getX(), p[0].getY());
|
||||
if (getPointCount() == PointCount.TWO) {
|
||||
path.lineTo(p[1].getX(), p[1].getY());
|
||||
} else if (getPointCount() == PointCount.THREE) {
|
||||
path.curveTo(p[1].getX(), p[1].getY(), p[1].getX(), p[1].getY(), p[2].getX(), p[2].getY());
|
||||
} else if (getPointCount() == PointCount.FOUR) {
|
||||
path.curveTo(p[1].getX(), p[1].getY(), p[2].getX(), p[2].getY(), p[3].getX(), p[3].getY());
|
||||
} else if (getPointCount() == PointCount.FIVE) {
|
||||
path.quadTo(p[1].getX(), p[1].getY(), p[2].getX(), p[2].getY());
|
||||
path.quadTo(p[3].getX(), p[3].getY(), p[4].getX(), p[4].getY());
|
||||
} else if (getPointCount() == PointCount.SEVEN) {
|
||||
path.curveTo(p[1].getX(), p[1].getY(), p[2].getX(), p[2].getY(), p[3].getX(), p[3].getY());
|
||||
path.curveTo(p[4].getX(), p[4].getY(), p[5].getX(), p[5].getY(), p[6].getX(), p[6].getY());
|
||||
}
|
||||
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
if (alpha < MAX_ALPHA) {
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
|
||||
}
|
||||
|
||||
drawCurve(path, g2d, componentState, drawingObserver);
|
||||
|
||||
g2d.setComposite(oldComposite);
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Point Count")
|
||||
public PointCount getPointCount() {
|
||||
if (pointCount == null) {
|
||||
pointCount = PointCount.FOUR;
|
||||
}
|
||||
return pointCount;
|
||||
}
|
||||
|
||||
protected Point2D[] getControlPoints() {
|
||||
if (this.controlPoints != null) {
|
||||
// ensure backward compatibility by copying points from the old structure to the new one
|
||||
switch (getPointCount()) {
|
||||
case TWO:
|
||||
this.controlPoints2 = new Point2D[2];
|
||||
this.controlPoints2[0] = this.controlPoints[0];
|
||||
this.controlPoints2[1] = this.controlPoints[3];
|
||||
break;
|
||||
case THREE:
|
||||
this.controlPoints2 = new Point2D[3];
|
||||
this.controlPoints2[0] = this.controlPoints[0];
|
||||
this.controlPoints2[1] = this.controlPoints[1];
|
||||
this.controlPoints2[2] = this.controlPoints[3];
|
||||
break;
|
||||
case FOUR:
|
||||
this.controlPoints2 = new Point2D[4];
|
||||
this.controlPoints2[0] = this.controlPoints[0];
|
||||
this.controlPoints2[1] = this.controlPoints[1];
|
||||
this.controlPoints2[2] = this.controlPoints[2];
|
||||
this.controlPoints2[3] = this.controlPoints[3];
|
||||
break;
|
||||
default: // shouldn't happen
|
||||
this.controlPoints2 = this.controlPoints;
|
||||
}
|
||||
// we don't need old points anymore
|
||||
this.controlPoints = null;
|
||||
}
|
||||
return this.controlPoints2;
|
||||
}
|
||||
|
||||
public void setPointCount(PointCount pointCount) {
|
||||
Point2D[] p = getControlPoints();
|
||||
Point2D[] newPoints = new Point2D[pointCount.count];
|
||||
newPoints[0] = p[0];
|
||||
newPoints[pointCount.count - 1] = p[p.length - 1];
|
||||
|
||||
if (pointCount == PointCount.THREE) {
|
||||
newPoints[1] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[0].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[0].getY()) / 2);
|
||||
} else if (pointCount == PointCount.FOUR) {
|
||||
newPoints[1] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[0].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[0].getY()) / 2);
|
||||
newPoints[2] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[0].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[0].getY()) / 2);
|
||||
} else if (pointCount == PointCount.FIVE) {
|
||||
newPoints[2] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[0].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[0].getY()) / 2);
|
||||
newPoints[1] = new Point2D.Double((newPoints[2].getX() + newPoints[0].getX()) / 2, (newPoints[2].getY() + newPoints[0].getY()) / 2);
|
||||
newPoints[3] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[2].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[2].getY()) / 2);
|
||||
} else if (pointCount == PointCount.SEVEN) {
|
||||
newPoints[3] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[0].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[0].getY()) / 2);
|
||||
newPoints[2] = new Point2D.Double((newPoints[3].getX() + newPoints[0].getX()) / 2, (newPoints[3].getY() + newPoints[0].getY()) / 2);
|
||||
newPoints[1] = new Point2D.Double((newPoints[3].getX() + newPoints[0].getX()) / 2, (newPoints[3].getY() + newPoints[0].getY()) / 2);
|
||||
newPoints[4] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[3].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[3].getY()) / 2);
|
||||
newPoints[5] =
|
||||
new Point2D.Double((newPoints[pointCount.count - 1].getX() + newPoints[3].getX()) / 2,
|
||||
(newPoints[pointCount.count - 1].getY() + newPoints[3].getY()) / 2);
|
||||
}
|
||||
|
||||
this.controlPoints2 = newPoints;
|
||||
this.pointCount = pointCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getControlPointCount() {
|
||||
return getControlPoints().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isControlPointSticky(int index) {
|
||||
return index == 0 || index == getControlPointCount() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
|
||||
return VisibilityPolicy.WHEN_SELECTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canControlPointOverlap(int index) {
|
||||
return index > 0 && index < getControlPointCount() - 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Point2D getControlPoint(int index) {
|
||||
return getControlPoints()[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setControlPoint(Point2D point, int index) {
|
||||
Point2D[] p = getControlPoints();
|
||||
p[index].setLocation(point);
|
||||
this.lastUpdatePointIndex = index;
|
||||
// if (getSmooth()) {
|
||||
// if (getPointCount() == PointCount.FIVE && (index == 1 || index == 2)) {
|
||||
// p[3] = findThirdPoint(p[2], p[1]);
|
||||
// }
|
||||
// if (getPointCount() == PointCount.FIVE && index == 3) {
|
||||
// p[1] = findThirdPoint(p[2], p[3]);
|
||||
// }
|
||||
// if (getPointCount() == PointCount.SEVEN && (index == 2 || index == 3)) {
|
||||
// p[4] = findThirdPoint(p[3], p[2]);
|
||||
// }
|
||||
// if (getPointCount() == PointCount.SEVEN && index == 4) {
|
||||
// p[2] = findThirdPoint(p[3], p[4]);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private Point2D findThirdPoint(Point2D p0, Point2D p) {
|
||||
return new Point2D.Double(2 * p0.getX() - p.getX(), 2 * p0.getY() - p.getY());
|
||||
}
|
||||
|
||||
@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
|
||||
public Boolean getSmooth() {
|
||||
if (smooth == null)
|
||||
this.smooth = true;
|
||||
return this.smooth;
|
||||
}
|
||||
|
||||
public void setSmooth(Boolean smooth) {
|
||||
this.smooth = smooth;
|
||||
// make the current curve smooth if needed
|
||||
// Point[] p = getControlPoints();
|
||||
// if (smooth) {
|
||||
// if (getPointCount() == PointCount.FIVE) {
|
||||
// p[3] = findThirdPoint(p[2], p[1]);
|
||||
// }
|
||||
// if (getPointCount() == PointCount.SEVEN) {
|
||||
// p[4] = findThirdPoint(p[3], p[2]);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@EditableProperty
|
||||
public Size getLength() {
|
||||
double d = 0;
|
||||
try {
|
||||
Point2D[] p = getControlPoints();
|
||||
if (getPointCount() == PointCount.TWO) {
|
||||
d = p[0].distance(p[1]);
|
||||
} else if (getPointCount() == PointCount.THREE) {
|
||||
d = calculateLength(p[0], p[1], p[1], p[2]);
|
||||
} else if (getPointCount() == PointCount.FOUR) {
|
||||
d = calculateLength(p[0], p[1], p[2], p[3]);
|
||||
} else if (getPointCount() == PointCount.FIVE) {
|
||||
d = calculateLength(p[0], p[1], p[2]) + calculateLength(p[2], p[3], p[4]);
|
||||
} else if (getPointCount() == PointCount.SEVEN) {
|
||||
d = calculateLength(p[0], p[1], p[2], p[3]) + calculateLength(p[3], p[4], p[5], p[6]);
|
||||
}
|
||||
|
||||
SizeUnit unit;
|
||||
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.METRIC_KEY, true))
|
||||
unit = SizeUnit.mm;
|
||||
else
|
||||
unit = SizeUnit.in;
|
||||
|
||||
d = d * SizeUnit.px.getFactor() / unit.getFactor();
|
||||
return new Size(d, unit);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error calculating length of " + getName(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
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 {
|
||||
TWO(2), THREE(3), FOUR(4), FIVE(5), SEVEN(7);
|
||||
|
||||
private int count;
|
||||
|
||||
private PointCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name().substring(0, 1) + name().substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
// calculate length of quad curve
|
||||
private double calculateLength(Point2D a, Point2D b, Point2D c) {
|
||||
double vx = 2 * (b.getX() - a.getX());
|
||||
double vy = 2 * (b.getY() - a.getY());
|
||||
double wx = c.getX() - 2 * b.getX() + a.getX();
|
||||
double wy = c.getY() - 2 * b.getY() + a.getY();
|
||||
|
||||
double uu = 4 * (wx * wx + wy * wy);
|
||||
|
||||
if (uu < 0.00001) {
|
||||
return (float) Math.sqrt((c.getX() - a.getX()) * (c.getX() - a.getX()) + (c.getY() - a.getY()) * (c.getY() - a.getY()));
|
||||
}
|
||||
|
||||
double vv = 4 * (vx * wx + vy * wy);
|
||||
double ww = vx * vx + vy * vy;
|
||||
|
||||
double t1 = (float) (2 * Math.sqrt(uu * (uu + vv + ww)));
|
||||
double t2 = 2 * uu + vv;
|
||||
double t3 = vv * vv - 4 * uu * ww;
|
||||
double t4 = (float) (2 * Math.sqrt(uu * ww));
|
||||
|
||||
return (float) ((t1 * t2 - t3 * Math.log(t2 + t1) - (vv * t4 - t3 * Math.log(vv + t4)))
|
||||
/ (8 * Math.pow(uu, 1.5)));
|
||||
}
|
||||
|
||||
// do not use this property
|
||||
@XStreamOmitField
|
||||
@Deprecated
|
||||
private double curveThreshold;
|
||||
|
||||
// tweak this value if needed
|
||||
private static final double curveDivisionThreshold = 5d;
|
||||
|
||||
// approximately calculate length of Bezier curves by subdivision
|
||||
private double calculateLength(Point2D a, Point2D b, Point2D c, Point2D d) {
|
||||
double distance = a.distance(d);
|
||||
if (distance < curveDivisionThreshold)
|
||||
return distance;
|
||||
CubicCurve2D curve = new CubicCurve2D.Double(a.getX(), a.getY(), b.getX(), b.getY(), c.getX(), c.getY(), d.getX(), d.getY());
|
||||
CubicCurve2D left = new CubicCurve2D.Double();
|
||||
CubicCurve2D right = new CubicCurve2D.Double();
|
||||
curve.subdivide(left, right);
|
||||
return calculateLength(left.getP1(), left.getCtrlP1(), left.getCtrlP2(), left.getP2()) +
|
||||
calculateLength(right.getP1(), right.getCtrlP1(), right.getCtrlP2(), right.getP2());
|
||||
}
|
||||
|
||||
protected List<CubicCurve2D> subdivide(double d) {
|
||||
Point2D[] p = getControlPoints();
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(p[0].getX(), p[0].getY());
|
||||
if (getPointCount() == PointCount.TWO) {
|
||||
List<CubicCurve2D> result = new ArrayList<CubicCurve2D>();
|
||||
result.add(new CubicCurve2D.Double(p[0].getX(), p[0].getY(),
|
||||
(p[0].getX() + p[1].getX()) / 2,
|
||||
(p[0].getY() + p[1].getY()) / 2,
|
||||
(p[0].getX() + p[1].getX()) / 2,
|
||||
(p[0].getY() + p[1].getY()) / 2,
|
||||
p[1].getX(), p[1].getY()));
|
||||
return result;
|
||||
} else if (getPointCount() == PointCount.THREE) {
|
||||
CubicCurve2D curve = new CubicCurve2D.Double(p[0].getX(), p[0].getY(),
|
||||
(p[0].getX() + 2 * p[1].getX()) / 3,
|
||||
(p[0].getY() + 2 * p[1].getY()) / 3,
|
||||
(p[2].getX() + 2 * p[1].getX()) / 3,
|
||||
(p[2].getY() + 2 * p[1].getY()) / 3,
|
||||
p[2].getX(), p[2].getY());
|
||||
return subdivide(curve, d);
|
||||
} else if (getPointCount() == PointCount.FOUR) {
|
||||
CubicCurve2D curve = new CubicCurve2D.Double(p[0].getX(), p[0].getY(),
|
||||
p[1].getX(), p[1].getY(),
|
||||
p[2].getX(), p[2].getY(),
|
||||
p[3].getX(), p[3].getY());
|
||||
return subdivide(curve, d);
|
||||
} else if (getPointCount() == PointCount.FIVE) {
|
||||
CubicCurve2D curve1 = new CubicCurve2D.Double(p[0].getX(), p[0].getY(),
|
||||
(p[0].getX() + 2 * p[1].getX()) / 3,
|
||||
(p[0].getY() + 2 * p[1].getY()) / 3,
|
||||
(p[2].getX() + 2 * p[1].getX()) / 3,
|
||||
(p[2].getY() + 2 * p[1].getY()) / 3,
|
||||
p[2].getX(), p[2].getY());
|
||||
CubicCurve2D curve2 = new CubicCurve2D.Double(p[2].getX(), p[2].getY(),
|
||||
(p[2].getX() + 2 * p[3].getX()) / 3,
|
||||
(p[2].getY() + 2 * p[3].getY()) / 3,
|
||||
(p[4].getX() + 2 * p[3].getX()) / 3,
|
||||
(p[4].getY() + 2 * p[3].getY()) / 3,
|
||||
p[4].getX(), p[4].getY());
|
||||
return Streams.concat(subdivide(curve1, d).stream(), subdivide(curve2, d).stream()).collect(Collectors.toList());
|
||||
} else if (getPointCount() == PointCount.SEVEN) {
|
||||
CubicCurve2D curve1 = new CubicCurve2D.Double(p[0].getX(), p[0].getY(),
|
||||
p[1].getX(), p[1].getY(),
|
||||
p[2].getX(), p[2].getY(),
|
||||
p[3].getX(), p[3].getY());
|
||||
CubicCurve2D curve2 = new CubicCurve2D.Double(p[3].getX(), p[3].getY(),
|
||||
p[4].getX(), p[4].getY(),
|
||||
p[5].getX(), p[5].getY(),
|
||||
p[6].getX(), p[6].getY());
|
||||
return Streams.concat(subdivide(curve1, d).stream(), subdivide(curve2, d).stream()).collect(Collectors.toList());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<CubicCurve2D> subdivide(CubicCurve2D curve, double d) {
|
||||
if (curve.getFlatness() < d || new Point2D.Double(curve.getX1(), curve.getY1()).distance(curve.getX2(), curve.getY2()) < d) {
|
||||
List<CubicCurve2D> result = new ArrayList<CubicCurve2D>();
|
||||
result.add(curve);
|
||||
return result;
|
||||
}
|
||||
CubicCurve2D left = new CubicCurve2D.Double();
|
||||
CubicCurve2D right = new CubicCurve2D.Double();
|
||||
curve.subdivide(left, right);
|
||||
return Streams.concat(subdivide(left, d).stream(), subdivide(right, d).stream()).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
public abstract class AbstractLabeledComponent<T> extends AbstractTransparentComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected Integer fontSizeOverride;
|
||||
|
||||
@EditableProperty(name = "Font Size Override")
|
||||
public Integer getFontSizeOverride() {
|
||||
return fontSizeOverride;
|
||||
}
|
||||
|
||||
public void setFontSizeOverride(Integer fontSizeOverride) {
|
||||
this.fontSizeOverride = fontSizeOverride;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
public abstract class AbstractTransparentComponent<T> extends AbstractComponent<T> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static byte MAX_ALPHA = 127;
|
||||
|
||||
protected byte alpha = MAX_ALPHA;
|
||||
|
||||
@EditableProperty
|
||||
public Byte getAlpha() {
|
||||
return alpha;
|
||||
}
|
||||
|
||||
public void setAlpha(Byte alpha) {
|
||||
this.alpha = alpha;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.IComponentTransformer;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class DefaultTransformer implements IComponentTransformer {
|
||||
|
||||
@Override
|
||||
public boolean canRotate(IDIYComponent<?> component) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMirror(IDIYComponent<?> component) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mirroringChangesCircuit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mirror(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import org.diylc.common.IComponentTransformer;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class LeadedComponentTransformer implements IComponentTransformer {
|
||||
|
||||
@Override
|
||||
public boolean canRotate(IDIYComponent<?> component) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMirror(IDIYComponent<?> component) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mirroringChangesCircuit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2 * direction, center.getX(), center.getY());
|
||||
for (int index = 0; index < component.getControlPointCount(); index++) {
|
||||
Point2D p = new Point2D.Double();
|
||||
rotate.transform(component.getControlPoint(index), p);
|
||||
component.setControlPoint(p, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mirror(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
for (int i = 0; i < component.getControlPointCount(); i++) {
|
||||
Point2D p = component.getControlPoint(i);
|
||||
if (direction == IComponentTransformer.HORIZONTAL) {
|
||||
component.setControlPoint(new Point2D.Double(p.getX() - 2 * (p.getX() - center.getX()), p.getY()), i);
|
||||
} else {
|
||||
component.setControlPoint(new Point2D.Double(p.getX(), p.getY() - 2 * (p.getY() - center.getY())), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.Point;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import org.diylc.common.IComponentTransformer;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
public class SimpleComponentTransformer implements IComponentTransformer {
|
||||
|
||||
@Override
|
||||
public boolean canRotate(IDIYComponent<?> component) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMirror(IDIYComponent<?> component) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mirroringChangesCircuit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
AffineTransform rotate = AffineTransform.getRotateInstance(Math.PI / 2 * direction, center.getX(), center.getY());
|
||||
for (int index = 0; index < component.getControlPointCount(); index++) {
|
||||
Point2D p = new Point2D.Double();
|
||||
rotate.transform(component.getControlPoint(index), p);
|
||||
component.setControlPoint(p, index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mirror(IDIYComponent<?> component, Point2D center, int direction) {
|
||||
for (int i = 0; i < component.getControlPointCount(); i++) {
|
||||
Point2D p = component.getControlPoint(i);
|
||||
if (direction == IComponentTransformer.HORIZONTAL) {
|
||||
component.setControlPoint(new Point2D.Double(p.getX() - 2 * (p.getX() - center.getX()), p.getY()), i);
|
||||
} else {
|
||||
component.setControlPoint(new Point.Double(p.getX(), p.getY() - 2 * (p.getY() - center.getY())), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Validator that allows all values.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class AllowAllValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object owner, Object value) throws ValidationException {}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.diylc.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class Angle {
|
||||
|
||||
private int value;
|
||||
|
||||
private Angle(int value) {
|
||||
super();
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public double getValueRad() {
|
||||
return Math.toRadians(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + value;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Angle other = (Angle) obj;
|
||||
if (value != other.value)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Integer.toString(value);
|
||||
}
|
||||
|
||||
private static Map<Integer, Angle> valueCache = new HashMap<Integer, Angle>();
|
||||
|
||||
public synchronized static Angle of(int angle) {
|
||||
int newValue = angle;
|
||||
while (newValue < 0)
|
||||
newValue += 360;
|
||||
while (newValue >= 360)
|
||||
newValue -= 360;
|
||||
return valueCache.computeIfAbsent(newValue, (value) -> new Angle(value));
|
||||
}
|
||||
|
||||
public Angle rotate(int direction) {
|
||||
int newValue = value + direction * 90;
|
||||
return Angle.of(newValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Component with all extra info for it to be rendered on the screen.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class ComponentForRender {
|
||||
|
||||
private IDIYComponent<?> component;
|
||||
private ComponentState state;
|
||||
private int zOrder;
|
||||
|
||||
public ComponentForRender(IDIYComponent<?> component, ComponentState state, int zOrder) {
|
||||
super();
|
||||
this.component = component;
|
||||
this.state = state;
|
||||
this.zOrder = zOrder;
|
||||
}
|
||||
|
||||
public IDIYComponent<?> getComponent() {
|
||||
return component;
|
||||
}
|
||||
|
||||
public ComponentState getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public int getZOrder() {
|
||||
return zOrder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Enumerates all possible states that a component can be in.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum ComponentState {
|
||||
|
||||
NORMAL, SELECTED, LOCKED, DRAGGING
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum CreationMethod {
|
||||
|
||||
SINGLE_CLICK, POINT_BY_POINT;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public enum ExpansionMode {
|
||||
|
||||
ALL, SAME_TYPE, IMMEDIATE,
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
*
|
||||
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 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;
|
||||
|
||||
public interface ICommonNode {
|
||||
|
||||
|
||||
/***
|
||||
* @return label of the common node. All nodes with the same labels will be considered as
|
||||
* connected, e.g. B+ or A, B, C
|
||||
*/
|
||||
String getCommonNodeLabel();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public interface IContinuity {
|
||||
|
||||
/**
|
||||
* Tests control point connectivity.
|
||||
*
|
||||
* @param index1
|
||||
* @param index2
|
||||
* @return true if the two points are connected, false otherwise.
|
||||
*/
|
||||
boolean arePointsConnected(int index1, int index2);
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 java.awt.Graphics2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.Serializable;
|
||||
import org.diylc.core.annotations.ComponentDescriptor;
|
||||
import org.diylc.core.annotations.EditableProperty;
|
||||
|
||||
/**
|
||||
* Interface for component instance. Implementation classes of this interface will be instantiated
|
||||
* by the application when component is added to the canvas. <br>
|
||||
* <br>
|
||||
* <b>Implementing classes should meet the following: </b>
|
||||
* <ul>
|
||||
* <li>Must have an empty constructor.</li>
|
||||
* <li>Class should be annotated with {@link ComponentDescriptor}.</li>
|
||||
* <li>Getters for properties editable by users should be annotated with {@link EditableProperty}.</li>
|
||||
* <li>Component configuration should be stored int <code>public static</code> fields so they can be
|
||||
* set through config file.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*
|
||||
* @param <T> type of component values, e.g. Resistance for resistors or String for transistors.
|
||||
*/
|
||||
public interface IDIYComponent<T> extends Serializable, Cloneable {
|
||||
|
||||
public static final int CHASSIS = 1;
|
||||
public static final int BOARD = 2;
|
||||
public static final int TRACE = 3;
|
||||
public static final int COMPONENT = 4;
|
||||
public static final int WIRING = 5;
|
||||
public static final int TEXT = 6;
|
||||
|
||||
/**
|
||||
* @return component instance name.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Updates component instance name.
|
||||
*
|
||||
* @param name
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* @return component value.
|
||||
*/
|
||||
T getValue();
|
||||
|
||||
/**
|
||||
* Updates component value.
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
void setValue(T value);
|
||||
|
||||
/**
|
||||
* @return number of control points for this component instance. May vary between two instances of
|
||||
* the same type, e.g. DIL IC with 8 and 16 pins will have 8 or 16 pins although they are
|
||||
* of the same type.
|
||||
*/
|
||||
int getControlPointCount();
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return control point at the specified index.
|
||||
*/
|
||||
Point2D getControlPoint(int index);
|
||||
|
||||
/**
|
||||
* Updates the control point at the specified index.
|
||||
*
|
||||
* @param point
|
||||
* @param index
|
||||
*/
|
||||
void setControlPoint(Point2D point, int index);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true, if the specified control point may stick to control points of other components.
|
||||
*/
|
||||
boolean isControlPointSticky(int index);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return true, if the specified control point may overlap with other control points <b>of the
|
||||
* same component</b>. The other control point must be able to overlap too.
|
||||
*/
|
||||
boolean canControlPointOverlap(int index);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return {@link VisibilityPolicy} of the control point.
|
||||
*/
|
||||
VisibilityPolicy getControlPointVisibilityPolicy(int index);
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* @return name of the control point node, if the control point represents a graph node, null otherwise.
|
||||
*/
|
||||
String getControlPointNodeName(int index);
|
||||
|
||||
/**
|
||||
* @param index1
|
||||
* @param index2
|
||||
* @return name of the internal linked formed by the two control points, null if they do not form an internal link
|
||||
*/
|
||||
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
|
||||
*/
|
||||
boolean canPointMoveFreely(int pointIndex);
|
||||
|
||||
/**
|
||||
* Draws the component onto the {@link Graphics2D}.
|
||||
*
|
||||
* @param g2d
|
||||
* @param componentState
|
||||
* @param outlineMode
|
||||
* @param project
|
||||
* @param drawingObserver
|
||||
*/
|
||||
void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||
IDrawingObserver drawingObserver);
|
||||
|
||||
/**
|
||||
* Draws icon representation of the component. This should not depend on component state, i.e. it
|
||||
* should be treated as a static method.
|
||||
*
|
||||
* @param g2d
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
void drawIcon(Graphics2D g2d, int width, int height);
|
||||
|
||||
/**
|
||||
* Clones the component.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
IDIYComponent<T> clone() throws CloneNotSupportedException;
|
||||
|
||||
/**
|
||||
* @return full value for BOM.
|
||||
*/
|
||||
String getValueForDisplay();
|
||||
|
||||
/**
|
||||
* Checks if two components are equal.
|
||||
*
|
||||
* @param other
|
||||
* @return
|
||||
*/
|
||||
boolean equalsTo(IDIYComponent<?> other);
|
||||
|
||||
/**
|
||||
* Used only if {@link ComponentDescriptor#enableCache()} is set to true.
|
||||
* @return
|
||||
*/
|
||||
Rectangle2D getCachingBounds();
|
||||
|
||||
/**
|
||||
* Notifies the component that it's being created in the context of the specified project
|
||||
*
|
||||
* @param project
|
||||
*/
|
||||
void createdIn(Project project);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public interface IDatasheetSupport {
|
||||
|
||||
void applyModel(String[] model);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Interface for tracking component drawing process. Components may use it to stop or restart
|
||||
* tracking. Anything drawn while tracking is stopped will not be added to the mouse hot-spot area.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IDrawingObserver {
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should start tracking the drawing process.
|
||||
*/
|
||||
void stopTracking();
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should stop tracking the drawing process.
|
||||
*/
|
||||
void startTracking();
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should start tracking conductive continuity areas.
|
||||
*
|
||||
* @param positive designates if the area should be additive or subtractive
|
||||
*/
|
||||
void startTrackingContinuityArea(boolean positive);
|
||||
|
||||
/**
|
||||
* Notifies the observer that it should stop tracking conductive continuity areas.
|
||||
*/
|
||||
void stopTrackingContinuityArea();
|
||||
|
||||
/**
|
||||
* Checks if we are tracking continuity ares.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isTrackingContinuityArea();
|
||||
|
||||
/**
|
||||
* Allows us to connect multiple disjoint continuity areas by specifying the same continuity markers.
|
||||
* By default it is set to null and does not connect disjoint areas.
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
void setContinuityMarker(String marker);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.diylc.core;
|
||||
|
||||
public interface ILayeredComponent {
|
||||
|
||||
int getLayerId();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Interface for validating property value changes.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IPropertyValidator {
|
||||
|
||||
/**
|
||||
* @param owner
|
||||
* @param value
|
||||
* @throws ValidationException if validation fails. Message will contain the reason.
|
||||
*/
|
||||
void validate(Object owner, Object value) throws ValidationException;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Interface for all component that can act as switches. They must have at least one position.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface ISwitch {
|
||||
|
||||
/**
|
||||
* @return a positive number of positions.
|
||||
*/
|
||||
int getPositionCount();
|
||||
|
||||
/**
|
||||
* @param position
|
||||
* @return name of switch positions, e.g. "ON", "OFF"...
|
||||
*/
|
||||
String getPositionName(int position);
|
||||
|
||||
/**
|
||||
* Tests control point connectivity.
|
||||
*
|
||||
* @param index1
|
||||
* @param index2
|
||||
* @param position
|
||||
* @return true if the two points are connected in the given switch position, false otherwise.
|
||||
*/
|
||||
boolean arePointsConnected(int index1, int index2, int position);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
|
||||
/**
|
||||
* Base interface for the main GUI component.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IView {
|
||||
|
||||
public static final int ERROR_MESSAGE = 0;
|
||||
public static final int INFORMATION_MESSAGE = 1;
|
||||
public static final int WARNING_MESSAGE = 2;
|
||||
public static final int QUESTION_MESSAGE = 3;
|
||||
public static final int PLAIN_MESSAGE = -1;
|
||||
public static final int DEFAULT_OPTION = -1;
|
||||
public static final int YES_NO_OPTION = 0;
|
||||
public static final int YES_NO_CANCEL_OPTION = 1;
|
||||
public static final int OK_CANCEL_OPTION = 2;
|
||||
public static final int YES_OPTION = 0;
|
||||
public static final int NO_OPTION = 1;
|
||||
public static final int CANCEL_OPTION = 2;
|
||||
public static final int OK_OPTION = 0;
|
||||
|
||||
public static final String CHECK_BOX_MENU_ITEM = "org.diylc.checkBoxMenuItem";
|
||||
public static final String RADIO_BUTTON_GROUP_KEY = "org.diylc.radioButtonGroup";
|
||||
|
||||
void showMessage(String message, String title, int messageType);
|
||||
|
||||
int showConfirmDialog(String message, String title, int optionType, int messageType);
|
||||
|
||||
boolean editProperties(List<PropertyWrapper> properties, Set<PropertyWrapper> defaultedProperties, String title);
|
||||
|
||||
String showInputDialog(String message, String title);
|
||||
|
||||
File promptFileSave();
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 java.awt.Font;
|
||||
import java.io.Serializable;
|
||||
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;
|
||||
import org.diylc.core.annotations.MultiLineText;
|
||||
import org.diylc.core.annotations.PositiveMeasureValidator;
|
||||
import org.diylc.core.annotations.PositiveNonZeroMeasureValidator;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
|
||||
/**
|
||||
* Entity class that defines a project. Contains project properties and a collection of
|
||||
* components.This class is serialized to file. Some filed getters are tagged with
|
||||
* {@link EditableProperty} to enable for user to edit them.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class Project implements Serializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public static String DEFAULT_TITLE = "New Project";
|
||||
public static Size DEFAULT_WIDTH = new Size(29d, SizeUnit.cm);
|
||||
public static Size DEFAULT_HEIGHT = new Size(21d, SizeUnit.cm);
|
||||
public static Size DEFAULT_GRID_SPACING = new Size(0.1d, SizeUnit.in);
|
||||
public static Font DEFAULT_FONT = new Font("Square721 BT", Font.PLAIN, 14);
|
||||
|
||||
private VersionNumber fileVersion;
|
||||
|
||||
private String title;
|
||||
private String author;
|
||||
private String description;
|
||||
private Size width;
|
||||
private Size height;
|
||||
private Size gridSpacing;
|
||||
private Integer dotSpacing;
|
||||
private List<IDIYComponent<?>> components;
|
||||
private Set<Set<IDIYComponent<?>>> groups;
|
||||
private Set<Integer> lockedLayers;
|
||||
private Set<IDIYComponent<?>> lockedComponents;
|
||||
private Set<Integer> hiddenLayers;
|
||||
private Font font = DEFAULT_FONT;
|
||||
|
||||
public Project() {
|
||||
components = new ArrayList<IDIYComponent<?>>();
|
||||
groups = new HashSet<Set<IDIYComponent<?>>>();
|
||||
lockedLayers = new HashSet<Integer>();
|
||||
hiddenLayers = new HashSet<Integer>();
|
||||
lockedComponents = new HashSet<IDIYComponent<?>>();
|
||||
title = DEFAULT_TITLE;
|
||||
author = System.getProperty("user.name");
|
||||
width = DEFAULT_WIDTH;
|
||||
height = DEFAULT_HEIGHT;
|
||||
gridSpacing = DEFAULT_GRID_SPACING;
|
||||
}
|
||||
|
||||
@EditableProperty(defaultable = false, sortOrder = 1)
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@EditableProperty(sortOrder = 3)
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
@MultiLineText
|
||||
@EditableProperty(defaultable = false, sortOrder = 2)
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@EditableProperty(sortOrder = 4)
|
||||
public Size getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(Size width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
@EditableProperty(sortOrder = 5)
|
||||
public Size getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(Size height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Grid Spacing", validatorClass = SpacingValidator.class, sortOrder = 6)
|
||||
public Size getGridSpacing() {
|
||||
return gridSpacing;
|
||||
}
|
||||
|
||||
public void setGridSpacing(Size gridSpacing) {
|
||||
this.gridSpacing = gridSpacing;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Dot Spacing", validatorClass = PositiveNonZeroMeasureValidator.class)
|
||||
public Integer getDotSpacing() {
|
||||
if (dotSpacing == null)
|
||||
dotSpacing = 1;
|
||||
return dotSpacing;
|
||||
}
|
||||
|
||||
public void setDotSpacing(Integer dotSpacing) {
|
||||
this.dotSpacing = dotSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of components sorted by z-order ascending.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<IDIYComponent<?>> getComponents() {
|
||||
return components;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of grouped components.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Set<Set<IDIYComponent<?>>> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
public Set<IDIYComponent<?>> getLockedComponents() {
|
||||
if (lockedComponents == null)
|
||||
lockedComponents = new HashSet<IDIYComponent<?>>();
|
||||
return lockedComponents;
|
||||
}
|
||||
|
||||
public Set<Integer> getLockedLayers() {
|
||||
return lockedLayers;
|
||||
}
|
||||
|
||||
public Set<Integer> getHiddenLayers() {
|
||||
if (hiddenLayers == null)
|
||||
hiddenLayers = new HashSet<Integer>();
|
||||
return hiddenLayers;
|
||||
}
|
||||
|
||||
public VersionNumber getFileVersion() {
|
||||
return fileVersion;
|
||||
}
|
||||
|
||||
public void setFileVersion(VersionNumber fileVersion) {
|
||||
this.fileVersion = fileVersion;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Default Font")
|
||||
public Font getFont() {
|
||||
if (font == null)
|
||||
font = DEFAULT_FONT;
|
||||
return font;
|
||||
}
|
||||
|
||||
public void setFont(Font font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
@EditableProperty(name = "Default Font Size")
|
||||
public int getFontSize() {
|
||||
if (font == null)
|
||||
font = DEFAULT_FONT;
|
||||
return font.getSize();
|
||||
}
|
||||
|
||||
public void setFontSize(int size) {
|
||||
font = font.deriveFont((float) size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((author == null) ? 0 : author.hashCode());
|
||||
result = prime * result + ((components == null) ? 0 : components.hashCode());
|
||||
result = prime * result + ((description == null) ? 0 : description.hashCode());
|
||||
result = prime * result + ((height == null) ? 0 : height.hashCode());
|
||||
result = prime * result + ((title == null) ? 0 : title.hashCode());
|
||||
result = prime * result + ((width == null) ? 0 : width.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;
|
||||
Project other = (Project) obj;
|
||||
if (author == null) {
|
||||
if (other.author != null)
|
||||
return false;
|
||||
} else if (!author.equals(other.author))
|
||||
return false;
|
||||
if (components == null) {
|
||||
if (other.components != null)
|
||||
return false;
|
||||
} else if (components.size() != other.components.size()) {
|
||||
return false;
|
||||
} else {
|
||||
Iterator<IDIYComponent<?>> i1 = components.iterator();
|
||||
Iterator<IDIYComponent<?>> i2 = other.components.iterator();
|
||||
while (i1.hasNext()) {
|
||||
IDIYComponent<?> c1 = i1.next();
|
||||
IDIYComponent<?> c2 = i2.next();
|
||||
if (!c1.equalsTo(c2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (description == null) {
|
||||
if (other.description != null)
|
||||
return false;
|
||||
} else if (!description.equals(other.description))
|
||||
return false;
|
||||
if (height == null) {
|
||||
if (other.height != null)
|
||||
return false;
|
||||
} else if (!height.equals(other.height))
|
||||
return false;
|
||||
if (title == null) {
|
||||
if (other.title != null)
|
||||
return false;
|
||||
} else if (!title.equals(other.title))
|
||||
return false;
|
||||
if (width == null) {
|
||||
if (other.width != null)
|
||||
return false;
|
||||
} else if (!width.equals(other.width))
|
||||
return false;
|
||||
if (gridSpacing == null) {
|
||||
if (other.gridSpacing != null)
|
||||
return false;
|
||||
} else if (!gridSpacing.equals(other.gridSpacing))
|
||||
return false;
|
||||
if (font == null) {
|
||||
if (other.font != null)
|
||||
return false;
|
||||
} else if (!font.getFamily().equals(other.font.getFamily()) || font.getSize() != other.font.getSize() || font.getStyle() != other.font.getStyle())
|
||||
return false;
|
||||
if (groups == null) {
|
||||
if (other.groups != null)
|
||||
return false;
|
||||
} else if (!groups.equals(other.groups))
|
||||
return false;
|
||||
if (lockedLayers == null) {
|
||||
if (other.lockedLayers != null)
|
||||
return false;
|
||||
} else if (!lockedLayers.equals(other.lockedLayers))
|
||||
return false;
|
||||
if (getLockedComponents() == null) {
|
||||
if (other.lockedComponents != null)
|
||||
return false;
|
||||
} else if (!getLockedComponents().equals(other.lockedComponents))
|
||||
return false;
|
||||
if (hiddenLayers == null) {
|
||||
if (other.hiddenLayers != null)
|
||||
return false;
|
||||
} else if (!hiddenLayers.equals(other.hiddenLayers))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public static class SpacingValidator extends PositiveMeasureValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object owner, Object value) throws ValidationException {
|
||||
super.validate(owner, value);
|
||||
Size size = (Size) value;
|
||||
if (size.compareTo(new Size(0.1d, SizeUnit.mm)) < 0) {
|
||||
throw new ValidationException("must be at least 0.1mm");
|
||||
}
|
||||
if (size.compareTo(new Size(1d, SizeUnit.in)) > 0) {
|
||||
throw new ValidationException("must be less than 1in");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Project clone() {
|
||||
Project project = new Project();
|
||||
project.setTitle(this.getTitle());
|
||||
project.setAuthor(this.getAuthor());
|
||||
project.setDescription(this.getDescription());
|
||||
project.setFileVersion(this.getFileVersion());
|
||||
project.setGridSpacing(this.getGridSpacing());
|
||||
project.setHeight(this.getHeight());
|
||||
project.setWidth(this.getWidth());
|
||||
project.getLockedLayers().addAll(this.getLockedLayers());
|
||||
project.getHiddenLayers().addAll(this.getHiddenLayers());
|
||||
project.setFont(this.getFont());
|
||||
|
||||
Map<IDIYComponent<?>, IDIYComponent<?>> cloneMap = new HashMap<IDIYComponent<?>, IDIYComponent<?>>();
|
||||
|
||||
for (IDIYComponent<?> component : this.components) {
|
||||
try {
|
||||
IDIYComponent<?> clone = component.clone();
|
||||
project.getComponents().add(clone);
|
||||
cloneMap.put(component, clone);
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
project.lockedComponents.add(cloneMap.get(component));
|
||||
}
|
||||
return project;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 java.awt.geom.Point2D;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Template {
|
||||
|
||||
private String name;
|
||||
private Map<String, Object> values;
|
||||
private List<Point2D> points;
|
||||
@SuppressWarnings("unused")
|
||||
@Deprecated
|
||||
private boolean defaultFlag;
|
||||
private LocalDateTime createdOn;
|
||||
|
||||
public Template() {
|
||||
}
|
||||
|
||||
public Template(String name, Map<String, Object> values, List<Point2D> points) {
|
||||
this(name, values, points, LocalDateTime.now());
|
||||
}
|
||||
|
||||
public Template(String name, Map<String, Object> values, List<Point2D> points, LocalDateTime createdOn) {
|
||||
this.name = name;
|
||||
this.values = values;
|
||||
this.points = points;
|
||||
this.createdOn = createdOn;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Map<String, Object> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(Map<String, Object> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public List<Point2D> getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public void setPoints(List<Point2D> points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedOn() {
|
||||
return createdOn;
|
||||
}
|
||||
|
||||
public void setCreatedOn(LocalDateTime createdOn) {
|
||||
this.createdOn = createdOn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((createdOn == null) ? 0 : createdOn.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((points == null) ? 0 : points.hashCode());
|
||||
result = prime * result + ((values == null) ? 0 : values.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;
|
||||
Template other = (Template) obj;
|
||||
if (createdOn == null) {
|
||||
if (other.createdOn != null)
|
||||
return false;
|
||||
} else if (!createdOn.equals(other.createdOn))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (points == null) {
|
||||
if (other.points != null)
|
||||
return false;
|
||||
} else if (!points.equals(other.points))
|
||||
return false;
|
||||
if (values == null) {
|
||||
if (other.values != null)
|
||||
return false;
|
||||
} else if (!values.equals(other.values))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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 java.awt.Color;
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Theme implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String name;
|
||||
private Color bgColor;
|
||||
private Color gridColor;
|
||||
private Color outlineColor;
|
||||
private Color dotColor;
|
||||
|
||||
public Theme(String name, Color bgColor, Color gridColor, Color dotColor, Color outlineColor) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.bgColor = bgColor;
|
||||
this.gridColor = gridColor;
|
||||
this.dotColor = dotColor;
|
||||
this.outlineColor = outlineColor;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Color getBgColor() {
|
||||
return bgColor;
|
||||
}
|
||||
|
||||
public Color getGridColor() {
|
||||
return gridColor;
|
||||
}
|
||||
|
||||
public Color getDotColor() {
|
||||
if (dotColor == null)
|
||||
dotColor = gridColor;
|
||||
return dotColor;
|
||||
}
|
||||
|
||||
public Color getOutlineColor() {
|
||||
return outlineColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.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;
|
||||
Theme other = (Theme) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
public class ValidationException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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;
|
||||
|
||||
/**
|
||||
* Enumerates control point visibility policies.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum VisibilityPolicy {
|
||||
|
||||
/**
|
||||
* Control point should be rendered all the time.
|
||||
*/
|
||||
ALWAYS,
|
||||
/**
|
||||
* Control point should be rendered only when the component is selected.
|
||||
*/
|
||||
WHEN_SELECTED,
|
||||
/**
|
||||
* Control point should not be rendered regardless of component selection.
|
||||
*/
|
||||
NEVER;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.diylc.core.annotations;
|
||||
|
||||
public enum BinaryType {
|
||||
IMAGE, SVG
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
/**
|
||||
* Tells the system how to represent components in the B.O.M.
|
||||
*
|
||||
* @see ComponentDescriptor
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum BomPolicy {
|
||||
SHOW_ALL_NAMES, SHOW_ONLY_TYPE_NAME, NEVER_SHOW,
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ByteArrayProperty {
|
||||
|
||||
public BinaryType binaryType();
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import org.diylc.common.DefaultComponentTransformer;
|
||||
import org.diylc.common.IComponentTransformer;
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Annotation that needs to be used for each {@link IDIYComponent} implementation. Describes
|
||||
* component properties and how component should be represented and interact with the rest of the
|
||||
* system.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ComponentDescriptor {
|
||||
|
||||
/**
|
||||
* @return component type name.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* @return component type description.
|
||||
*/
|
||||
String description();
|
||||
|
||||
/**
|
||||
* @return method that should be used to create a component. If
|
||||
* <code>CreationMethod.POINT_BY_POINT</code> is used, user will have to select ending
|
||||
* points before the component is created.
|
||||
*/
|
||||
CreationMethod creationMethod() default CreationMethod.SINGLE_CLICK;
|
||||
|
||||
/**
|
||||
* @return component category, e.g. "Passive", "Semiconductors", etc.
|
||||
*/
|
||||
String category();
|
||||
|
||||
/**
|
||||
* @return component author name.
|
||||
*/
|
||||
String author();
|
||||
|
||||
/**
|
||||
* @return prefix that will be used to generate component instance names, e.g. "R" for resistors
|
||||
* or "Q" for transistors.
|
||||
*/
|
||||
String instanceNamePrefix();
|
||||
|
||||
/**
|
||||
* @return Z-order of the component.
|
||||
*/
|
||||
double zOrder();
|
||||
|
||||
/**
|
||||
* @return true if the component may go beyond it's predefined layer without warning the user.
|
||||
*/
|
||||
boolean flexibleZOrder() default false;
|
||||
|
||||
/**
|
||||
* @return controls what should be shown the BOM
|
||||
*/
|
||||
BomPolicy bomPolicy() default BomPolicy.SHOW_ALL_NAMES;
|
||||
|
||||
/**
|
||||
* @return when true, component editor dialog should be shown in Auto-Edit mode.
|
||||
*/
|
||||
boolean autoEdit() default true;
|
||||
|
||||
/**
|
||||
* @return if the component can be rotated and/or mirrored, returns a class of the transformer that can do it
|
||||
*/
|
||||
Class<? extends IComponentTransformer> transformer() default DefaultComponentTransformer.class;
|
||||
|
||||
/**
|
||||
* Defines if and how a component should appear in auto-generated project keywords. See
|
||||
* {@link KeywordPolicy} for more info.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
KeywordPolicy keywordPolicy() default KeywordPolicy.NEVER_SHOW;
|
||||
|
||||
/**
|
||||
* Only used if {@link KeywordPolicy} is set to {@link KeywordPolicy#SHOW_TAG}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String keywordTag() default "";
|
||||
|
||||
/**
|
||||
* @return true if the component drawing should be cached
|
||||
*/
|
||||
boolean enableCache() default false;
|
||||
|
||||
/**
|
||||
* @return true if component datasheet should be loaded from the corresponding file
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int datasheetCreationStepCount() default 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DynamicList {
|
||||
|
||||
public String availableValueFunction();
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import org.diylc.core.AllowAllValidator;
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
|
||||
/**
|
||||
* Used to annotate editable component property. Editable property XYZ must have both getter and
|
||||
* setter named <code>getXYZ</code> and <code>setXYZ</code> respectively and this annotation must be
|
||||
* placed on the getter method. <br>
|
||||
* <br>
|
||||
* In the example below, {@code category} is the property we want to edit and
|
||||
* {@code getCategories()} provides a list of available values for category.
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* @EditableProperty(additionalOptions = EditableProperty.DYNAMIC_LIST
|
||||
* + "getCategories")
|
||||
* public String getCategory() {
|
||||
* return category;
|
||||
* }
|
||||
*
|
||||
* public String[] getCategories() {
|
||||
* return categories;
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EditableProperty {
|
||||
|
||||
/**
|
||||
* Returns property name. If left blank property name will be extracted from the getter name, e.g.
|
||||
* getter <code>getXYZ</code> will induce property name <code>XYZ</code>. <br>
|
||||
* Default value is blank.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* If true, application may set default value for this property. <br>
|
||||
* Default value is true.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean defaultable() default true;
|
||||
|
||||
/**
|
||||
* Class of validator to use to
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Class<? extends IPropertyValidator> validatorClass() default AllowAllValidator.class;
|
||||
|
||||
/**
|
||||
* Optional parameter in case we want to force an order of properties.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
int sortOrder() default 100;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
public @interface ElementLabel {
|
||||
|
||||
public String functionName();
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.util.List;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
|
||||
/**
|
||||
* Interface for creating components automatically each time a component is created by the user.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public interface IAutoCreator {
|
||||
|
||||
/**
|
||||
* @param lastAdded the component created by the user
|
||||
* @return {@link List} of {@link IDIYComponent}s that will be automatically created as a result.
|
||||
* Empty {@link List} or {@code null} are valid responses for cases when no components
|
||||
* should be auto-created.
|
||||
*/
|
||||
public List<IDIYComponent<?>> createIfNeeded(IDIYComponent<?> lastAdded);
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
/**
|
||||
* Tells the system how keywords should be extracted from a component.
|
||||
*
|
||||
* @see ComponentDescriptor
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum KeywordPolicy {
|
||||
/**
|
||||
* The component is represented with its type.
|
||||
*/
|
||||
SHOW_TYPE_NAME,
|
||||
/**
|
||||
* The component is represented with its value.
|
||||
*/
|
||||
SHOW_VALUE,
|
||||
/**
|
||||
* The component is not important enough and will not be shown in the keywords.
|
||||
*/
|
||||
NEVER_SHOW,
|
||||
/**
|
||||
* The component is represented with the value of {@link ComponentDescriptor#keywordTag()}
|
||||
*/
|
||||
SHOW_TAG,
|
||||
/**
|
||||
* The component is represented with both the value of {@link ComponentDescriptor#keywordTag()}
|
||||
* and the actual component value
|
||||
*/
|
||||
SHOW_TAG_AND_VALUE,
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MultiLineText {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PercentEditor {
|
||||
|
||||
public byte _100PercentValue();
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.ValidationException;
|
||||
import org.diylc.core.measures.AbstractMeasure;
|
||||
|
||||
/**
|
||||
* Validates any generic {@link AbstractMeasure} descendants and makes sure that the value is
|
||||
* positive.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class PositiveMeasureValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object owner, Object value) throws ValidationException {
|
||||
if (value == null)
|
||||
return;
|
||||
if (value instanceof AbstractMeasure) {
|
||||
AbstractMeasure<?> measure = (AbstractMeasure<?>) value;
|
||||
if (measure.getValue() < 0) {
|
||||
throw new ValidationException("must be greater or equal to zero.");
|
||||
}
|
||||
} else if (value instanceof Integer) {
|
||||
Integer i = (Integer) value;
|
||||
if (i < 0)
|
||||
throw new ValidationException("must be greater or equal to zero.");
|
||||
} else {
|
||||
throw new ValidationException("wrong data type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.annotations;
|
||||
|
||||
import org.diylc.core.IPropertyValidator;
|
||||
import org.diylc.core.ValidationException;
|
||||
import org.diylc.core.measures.AbstractMeasure;
|
||||
|
||||
/**
|
||||
* Validates any generic {@link AbstractMeasure} descendants and makes sure that the value is
|
||||
* positive.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public class PositiveNonZeroMeasureValidator implements IPropertyValidator {
|
||||
|
||||
@Override
|
||||
public void validate(Object owner, Object value) throws ValidationException {
|
||||
if (value == null)
|
||||
return;
|
||||
if (value instanceof AbstractMeasure) {
|
||||
AbstractMeasure<?> measure = (AbstractMeasure<?>) value;
|
||||
if (measure.getValue() <= 0) {
|
||||
throw new ValidationException("must be greater than zero.");
|
||||
}
|
||||
} else if (value instanceof Integer) {
|
||||
Integer i = (Integer) value;
|
||||
if (i < 0)
|
||||
throw new ValidationException("must be greater or equal to zero.");
|
||||
} else {
|
||||
throw new ValidationException("wrong data type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.IView;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.lang.LangUtil;
|
||||
import com.bancika.gerberwriter.DataLayer;
|
||||
|
||||
public class GerberExporter {
|
||||
|
||||
public static final double OUTLINE_THICKNESS = new Size(0.3d, SizeUnit.mm).convertToPixels();
|
||||
private static final Logger LOG = Logger.getLogger(GerberExporter.class);
|
||||
|
||||
public static void exportGerber(String fileNameBase, Project currentProject, IView view,
|
||||
Graphics2D graphics2d, String diylcVersion) {
|
||||
List<IGerberBoard> gerberBoards =
|
||||
currentProject.getComponents().stream().filter(c -> c instanceof IGerberBoard)
|
||||
.map(x -> (IGerberBoard) x).collect(Collectors.toList());
|
||||
|
||||
Map<IGerberBoard, List<IDIYComponent<?>>> boardComponentMap =
|
||||
new HashMap<IGerberBoard, List<IDIYComponent<?>>>();
|
||||
|
||||
// DefaultGerberBoard defaultGerberBoard = new DefaultGerberBoard();
|
||||
|
||||
List<IDIYComponent<?>> componentsWithoutBoard = new ArrayList<IDIYComponent<?>>();
|
||||
|
||||
currentProject.getComponents().stream().filter(c -> c instanceof IGerberComponent)
|
||||
.forEach(c -> {
|
||||
Point2D firstPoint = c.getControlPoint(0);
|
||||
IGerberBoard board = gerberBoards.stream()
|
||||
.filter(b -> b.getBoardRectangle().contains(firstPoint)).findFirst().orElse(null);
|
||||
if (board == null) {
|
||||
componentsWithoutBoard.add(c);
|
||||
} else {
|
||||
boardComponentMap.computeIfAbsent(board, k -> new ArrayList<IDIYComponent<?>>()).add(c);
|
||||
}
|
||||
});
|
||||
|
||||
// defaultGerberBoard.setComponents(boardComponentMap.get(defaultGerberBoard));
|
||||
|
||||
if (boardComponentMap.isEmpty()) {
|
||||
view.showMessage(LangUtil.translate("Nothing to export."),
|
||||
LangUtil.translate("Gerber Export"), IView.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (componentsWithoutBoard.size() > 0) {
|
||||
if (view.showConfirmDialog(String.format(
|
||||
LangUtil.translate("There are some components that are outside of the bounds of boards.%s"
|
||||
+ "They will be ignored unless you add a board component underneath them.%sDo you want to continue?"),
|
||||
"\n", "\n"), LangUtil.translate("Gerber Export"), IView.YES_NO_OPTION,
|
||||
IView.WARNING_MESSAGE) != IView.YES_OPTION) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<String> generatedFiles = new ArrayList<String>();
|
||||
|
||||
gerberBoards.forEach(b -> {
|
||||
IDIYComponent<?> boardComponent = (IDIYComponent<?>) b;
|
||||
|
||||
GerberLayer gerberLayer = GerberLayer.Outline;
|
||||
DataLayer outlineLayer = gerberLayer.buildLayer(diylcVersion);
|
||||
Rectangle2D boardRect = b.getBoardRectangle();
|
||||
|
||||
final AffineTransform boardTx = AffineTransform.getScaleInstance(1, -1);
|
||||
boardTx.translate(-boardRect.getX(), -boardRect.getMaxY());
|
||||
final PathIterator pathIterator = boardRect.getPathIterator(boardTx);
|
||||
GerberPathRenderer.outputPathOutline(pathIterator, outlineLayer, 1d, false, "Profile", OUTLINE_THICKNESS);
|
||||
String fileNameOutline = GerberLayer.Outline.formatFileName(fileNameBase, boardComponent.getName());
|
||||
try {
|
||||
LOG.info(String.format(LangUtil.translate("Exporting outline for board %s to file %s"),
|
||||
boardComponent.getName(), fileNameOutline));
|
||||
outlineLayer.dumpGerberToFile(fileNameOutline);
|
||||
generatedFiles.add(fileNameOutline);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error writing gerber file: " + e.getMessage());
|
||||
view.showMessage(
|
||||
LangUtil.translate(
|
||||
"Failed to export the project to gerber. Please check the log for details"),
|
||||
LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
GerberG2DWrapper g2d = new GerberG2DWrapper(graphics2d, diylcVersion, boardRect);
|
||||
|
||||
boardComponentMap.get(b).forEach(c -> {
|
||||
IGerberComponent gerberComponent = (IGerberComponent) c;
|
||||
Set<GerberRenderMode> supportedRenderModes = gerberComponent.getGerberRenderModes();
|
||||
if (supportedRenderModes.contains(GerberRenderMode.Normal)) {
|
||||
drawComponent(currentProject, g2d, c, false);
|
||||
}
|
||||
if (supportedRenderModes.contains(GerberRenderMode.Outline)) {
|
||||
drawComponent(currentProject, g2d, c, true);
|
||||
}
|
||||
});
|
||||
|
||||
g2d.getLayerMap().entrySet().forEach(entry -> {
|
||||
org.diylc.core.gerber.GerberLayer layer = entry.getKey();
|
||||
DataLayer dataLayer = entry.getValue();
|
||||
try {
|
||||
String fileName = layer.formatFileName(fileNameBase, boardComponent.getName());
|
||||
LOG.info("Exporting layer: " + layer + " for board " + boardComponent.getName()
|
||||
+ " to file: " + fileName);
|
||||
dataLayer.dumpGerberToFile(fileName);
|
||||
generatedFiles.add(fileName);
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error writing gerber file: " + e.getMessage());
|
||||
view.showMessage(
|
||||
LangUtil.translate(
|
||||
"Failed to export the project to gerber. Please check the log for details"),
|
||||
LangUtil.translate("Gerber Export"), IView.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
view.showMessage(
|
||||
String.format(
|
||||
LangUtil.translate(
|
||||
"Gerber export completed successfully. The following files were created:%s"),
|
||||
"\n\n" + String.join("\n", generatedFiles)),
|
||||
LangUtil.translate("Gerber Export"), IView.INFORMATION_MESSAGE);
|
||||
LOG.info("Completed export to gerber");
|
||||
}
|
||||
|
||||
private static void drawComponent(Project currentProject, GerberG2DWrapper g2d,
|
||||
IDIYComponent<?> c, boolean outlineMode) {
|
||||
IGerberComponent gerberComponent = (IGerberComponent) c;
|
||||
g2d.startedDrawingComponent();
|
||||
if (gerberComponent instanceof IGerberComponentCustom) {
|
||||
IGerberComponentCustom gerberComponentCustom = (IGerberComponentCustom) gerberComponent;
|
||||
gerberComponentCustom.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d, g2d);
|
||||
} else if (gerberComponent instanceof IGerberComponentSimple) {
|
||||
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
|
||||
g2d.startGerberOutput(gerberComponentSimple.getGerberLayer(),
|
||||
gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
|
||||
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
|
||||
g2d.stopGerberOutput();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,552 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.RenderingHints.Key;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Ellipse2D;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
import java.awt.image.ImageObserver;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.awt.image.renderable.RenderableImage;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
import com.bancika.gerberwriter.DataLayer;
|
||||
import com.bancika.gerberwriter.Point;
|
||||
import com.bancika.gerberwriter.padmasters.Circle;
|
||||
|
||||
public class GerberG2DWrapper extends Graphics2D
|
||||
implements IDrawingObserver, IGerberDrawingObserver {
|
||||
|
||||
private static final double CURVE_APPROXIMATION_TOLERANCE = 1d;
|
||||
|
||||
private Map<GerberLayer, DataLayer> layerMap;
|
||||
private boolean trackingGerber = false;
|
||||
private Map<GerberLayer, GerberProperties> currentLayers =
|
||||
new HashMap<GerberLayer, GerberProperties>();
|
||||
private String diylcVersion;
|
||||
|
||||
private Graphics2D graphics2d;
|
||||
private Color color;
|
||||
private Stroke stroke;
|
||||
private Font font;
|
||||
private AffineTransform tx;
|
||||
private double tolerance;
|
||||
|
||||
private Rectangle2D boardRect;
|
||||
|
||||
public GerberG2DWrapper(Graphics2D graphics2d, String diylcVersion, Rectangle2D boardRect) {
|
||||
super();
|
||||
this.graphics2d = graphics2d;
|
||||
this.boardRect = boardRect;
|
||||
this.layerMap = new HashMap<GerberLayer, DataLayer>();
|
||||
this.diylcVersion = diylcVersion;
|
||||
}
|
||||
|
||||
public void startedDrawingComponent() {
|
||||
this.tx = new AffineTransform();
|
||||
this.tolerance = Double.NaN;
|
||||
}
|
||||
|
||||
public boolean isTrackingGerber() {
|
||||
return trackingGerber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopTracking() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTracking() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startTrackingContinuityArea(boolean positive) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopTrackingContinuityArea() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTrackingContinuityArea() {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContinuityMarker(String marker) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startGerberOutput(GerberLayer layer, String function, boolean negative) {
|
||||
layerMap.computeIfAbsent(layer, k -> layer.buildLayer(diylcVersion));
|
||||
currentLayers.put(layer, new GerberProperties(function, negative));
|
||||
trackingGerber = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGerberFunction(GerberLayer layer, String function) {
|
||||
currentLayers.get(layer).function = function;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGerberNegative(GerberLayer layer, boolean negative) {
|
||||
currentLayers.get(layer).negative = negative;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApproximationToleranceOverride(double tolerance) {
|
||||
this.tolerance = tolerance;
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopGerberOutput(GerberLayer layer) {
|
||||
currentLayers.remove(layer);
|
||||
if (currentLayers.isEmpty()) {
|
||||
trackingGerber = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopGerberOutput() {
|
||||
currentLayers.clear();
|
||||
trackingGerber = false;
|
||||
}
|
||||
|
||||
public Map<GerberLayer, DataLayer> getLayerMap() {
|
||||
return layerMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Shape s) {
|
||||
if (trackingGerber && !getColor().equals(Constants.TRANSPARENT_COLOR)) {
|
||||
currentLayers.entrySet().forEach(entry -> {
|
||||
double width = 1;
|
||||
if (stroke != null && stroke instanceof BasicStroke) {
|
||||
width = ((BasicStroke) stroke).getLineWidth();
|
||||
}
|
||||
DataLayer dataLayer = layerMap.get(entry.getKey());
|
||||
AffineTransform finalTx = getFinalTx(entry.getKey().isMirrored());
|
||||
GerberPathRenderer.outputPathOutline(s.getPathIterator(finalTx), dataLayer,
|
||||
Double.isNaN(tolerance) ? CURVE_APPROXIMATION_TOLERANCE : tolerance,
|
||||
entry.getValue().negative, entry.getValue().function, width);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, float x, float y) {
|
||||
if (str == null || str.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GlyphVector gv = font.createGlyphVector(graphics2d.getFontRenderContext(), str);
|
||||
|
||||
AffineTransform translateInstance = AffineTransform.getTranslateInstance(x, y);
|
||||
|
||||
for (int i = 0; i < gv.getNumGlyphs(); i++) {
|
||||
Shape glyphShape = gv.getGlyphOutline(i);
|
||||
|
||||
fillShape(translateInstance.createTransformedShape(glyphShape));
|
||||
}
|
||||
|
||||
// Font f = getFont();
|
||||
// TextLayout layout = new TextLayout(str, f, graphics2d.getFontRenderContext());
|
||||
// Shape shape = layout.getOutline(AffineTransform.getTranslateInstance(x, y));
|
||||
// fillShape(shape);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(Shape s) {
|
||||
if (s instanceof Ellipse2D
|
||||
&& (((Ellipse2D) s).getWidth() - ((Ellipse2D) s).getHeight()) < 0.1) {
|
||||
Ellipse2D e = (Ellipse2D) s;
|
||||
fillFlash(e);
|
||||
} else {
|
||||
fillShape(s);
|
||||
}
|
||||
}
|
||||
|
||||
public void fillShape(Shape s) {
|
||||
if (trackingGerber && !getColor().equals(Constants.TRANSPARENT_COLOR)) {
|
||||
currentLayers.entrySet().forEach(entry -> {
|
||||
DataLayer dataLayer = layerMap.get(entry.getKey());
|
||||
AffineTransform finalTx = getFinalTx(entry.getKey().isMirrored());
|
||||
GerberPathRenderer.outputPathArea(s.getPathIterator(finalTx), dataLayer,
|
||||
Double.isNaN(tolerance) ? CURVE_APPROXIMATION_TOLERANCE : tolerance,
|
||||
entry.getValue().negative, entry.getValue().function);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void fillFlash(Ellipse2D c) {
|
||||
if (trackingGerber && !getColor().equals(Constants.TRANSPARENT_COLOR)) {
|
||||
currentLayers.entrySet().forEach(entry -> {
|
||||
DataLayer dataLayer = layerMap.get(entry.getKey());
|
||||
AffineTransform finalTx = getFinalTx(entry.getKey().isMirrored());
|
||||
if (Math.abs(c.getWidth() - c.getHeight()) < 0.1 && finalTx.getShearX() == 0
|
||||
&& finalTx.getShearY() == 0
|
||||
&& Math.abs(Math.abs(finalTx.getScaleX()) - Math.abs(finalTx.getScaleY())) < 0.0001) {
|
||||
|
||||
final double d = Math.abs(c.getWidth() * finalTx.getScaleX()) * SizeUnit.px.getFactor();
|
||||
Circle circle = new Circle(d, entry.getValue().function, entry.getValue().negative);
|
||||
dataLayer.addPad(circle, new Point(
|
||||
(c.getX() * finalTx.getScaleX() + finalTx.getTranslateX()) * SizeUnit.px.getFactor()
|
||||
+ (entry.getKey().isMirrored() ? -1 : 1) * d / 2,
|
||||
(c.getY() * finalTx.getScaleY() + finalTx.getTranslateY()) * SizeUnit.px.getFactor()
|
||||
- d / 2));
|
||||
} else {
|
||||
// not a circle after transformation, default to polygon approximation
|
||||
fillShape(c);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private AffineTransform getFinalTx(boolean isMirrored) {
|
||||
AffineTransform finalTx = new AffineTransform();
|
||||
if (isMirrored) {
|
||||
finalTx.translate(boardRect.getWidth(), 0);
|
||||
finalTx.scale(-1, 1);
|
||||
}
|
||||
finalTx.scale(1, -1);
|
||||
finalTx.translate(-boardRect.getMinX(), -boardRect.getMaxY());
|
||||
finalTx.concatenate(tx);
|
||||
return finalTx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RenderingHints getRenderingHints() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(int x, int y) {
|
||||
this.tx.translate(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translate(double tx, double ty) {
|
||||
this.tx.translate(tx, ty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta) {
|
||||
this.tx.rotate(theta);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rotate(double theta, double x, double y) {
|
||||
this.tx.rotate(theta, x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scale(double sx, double sy) {
|
||||
this.tx.scale(sx, sy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shear(double shx, double shy) {
|
||||
this.tx.shear(shx, shy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(AffineTransform Tx) {
|
||||
this.tx.concatenate(Tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(AffineTransform Tx) {
|
||||
this.tx = Tx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getTransform() {
|
||||
return tx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontRenderContext getFontRenderContext() {
|
||||
return graphics2d.getFontRenderContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(Color c) {
|
||||
this.color = c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Font getFont() {
|
||||
return this.font;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFont(Font font) {
|
||||
this.font = font;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FontMetrics getFontMetrics(Font f) {
|
||||
return graphics2d.getFontMetrics(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStroke(Stroke s) {
|
||||
this.stroke = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stroke getStroke() {
|
||||
return stroke;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
|
||||
fillShape(new Polygon(xPoints, yPoints, nPoints));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawString(String str, int x, int y) {
|
||||
drawString(str, (float) x, (float) y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLine(int x1, int y1, int x2, int y2) {
|
||||
draw(new Line2D.Double(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillRect(int x, int y, int width, int height) {
|
||||
fillShape(new Rectangle2D.Double(x, y, width, height));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawOval(int x, int y, int width, int height) {
|
||||
draw(new Ellipse2D.Double(x, y, width, height));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillOval(int x, int y, int width, int height) {
|
||||
if (width == height) {
|
||||
fillFlash(new Ellipse2D.Double(x, y, width, height));
|
||||
} else {
|
||||
fillShape(new Ellipse2D.Double(x, y, width, height));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) {}
|
||||
|
||||
@Override
|
||||
public void drawRenderedImage(RenderedImage img, AffineTransform xform) {}
|
||||
|
||||
@Override
|
||||
public void drawRenderableImage(RenderableImage img, AffineTransform xform) {}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, int x, int y) {}
|
||||
|
||||
@Override
|
||||
public void drawString(AttributedCharacterIterator iterator, float x, float y) {}
|
||||
|
||||
@Override
|
||||
public void drawGlyphVector(GlyphVector g, float x, float y) {}
|
||||
|
||||
@Override
|
||||
public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComposite(Composite comp) {}
|
||||
|
||||
@Override
|
||||
public void setPaint(Paint paint) {}
|
||||
|
||||
@Override
|
||||
public void setRenderingHint(Key hintKey, Object hintValue) {}
|
||||
|
||||
@Override
|
||||
public Object getRenderingHint(Key hintKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderingHints(Map<?, ?> hints) {}
|
||||
|
||||
@Override
|
||||
public void addRenderingHints(Map<?, ?> hints) {}
|
||||
|
||||
@Override
|
||||
public Paint getPaint() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Composite getComposite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBackground(Color color) {}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clip(Shape s) {}
|
||||
|
||||
@Override
|
||||
public Graphics create() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPaintMode() {}
|
||||
|
||||
@Override
|
||||
public void setXORMode(Color c1) {}
|
||||
|
||||
@Override
|
||||
public Rectangle getClipBounds() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clipRect(int x, int y, int width, int height) {}
|
||||
|
||||
@Override
|
||||
public void setClip(int x, int y, int width, int height) {}
|
||||
|
||||
@Override
|
||||
public Shape getClip() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClip(Shape clip) {}
|
||||
|
||||
@Override
|
||||
public void copyArea(int x, int y, int width, int height, int dx, int dy) {}
|
||||
|
||||
@Override
|
||||
public void clearRect(int x, int y, int width, int height) {}
|
||||
|
||||
@Override
|
||||
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {}
|
||||
|
||||
@Override
|
||||
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {}
|
||||
|
||||
@Override
|
||||
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {}
|
||||
|
||||
@Override
|
||||
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {}
|
||||
|
||||
@Override
|
||||
public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {}
|
||||
|
||||
@Override
|
||||
public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor,
|
||||
ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2,
|
||||
int sy2, ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2,
|
||||
int sy2, Color bgcolor, ImageObserver observer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {}
|
||||
|
||||
static class GerberProperties {
|
||||
String function;
|
||||
boolean negative;
|
||||
|
||||
public GerberProperties(String function, boolean negative) {
|
||||
super();
|
||||
this.function = function;
|
||||
this.negative = negative;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import com.bancika.gerberwriter.DataLayer;
|
||||
import com.bancika.gerberwriter.GenerationSoftware;
|
||||
|
||||
public enum GerberLayer {
|
||||
|
||||
Outline("Profile,NP", "gko", "Edge-Cuts", false, false),
|
||||
DrillNonPlated("NonPlated,1,2,NPTH", "drl", "NPTH", false, false),
|
||||
DrillPlated("Plated,1,2,PTH", "drl", "PTH", false, false),
|
||||
CopperBot("Copper,L1,Bot", "gbl", "B_Cu", false, false),
|
||||
CopperTop("Copper,L1,Top", "gtl", "T_Cu", false, false),
|
||||
SilkscreenBot("Legend,Bot", "gbo", "B_Silkscreen", false, false),
|
||||
SilkscreenTop("Legend,Top", "gto", "T_Silkscreen", false, false),
|
||||
SolderMaskBot("Soldermask,Bot", "gbs", "B_Mask", true, false),
|
||||
SolderMaskTop("Soldermask,Top", "gts", "T_Mask", true, false);
|
||||
|
||||
private String function;
|
||||
private String extension;
|
||||
private boolean negative;
|
||||
private boolean mirrored;
|
||||
private String suffix;
|
||||
|
||||
private GerberLayer(String function, String extension, String suffix, boolean negative, boolean mirrored) {
|
||||
this.function = function;
|
||||
this.extension = extension;
|
||||
this.suffix = suffix;
|
||||
this.negative = negative;
|
||||
this.mirrored = mirrored;
|
||||
}
|
||||
|
||||
public DataLayer buildLayer(String diylcVersion) {
|
||||
GenerationSoftware genSoftware =
|
||||
new GenerationSoftware("bancika", "DIY Layout Creator", diylcVersion);
|
||||
return new DataLayer(function, negative, genSoftware);
|
||||
}
|
||||
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
public String getSuffix() {
|
||||
return suffix;
|
||||
}
|
||||
|
||||
public String getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public boolean isNegative() {
|
||||
return negative;
|
||||
}
|
||||
|
||||
public boolean isMirrored() {
|
||||
return mirrored;
|
||||
}
|
||||
|
||||
public String formatFileName(String fileNameBase, String boardName) {
|
||||
return fileNameBase + (fileNameBase.endsWith(".") ? "" : ".")
|
||||
+ boardName + "-" + getSuffix() + "." + getExtension();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.CubicCurve2D;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.QuadCurve2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import javax.imageio.ImageIO;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDIYComponent;
|
||||
import org.diylc.core.Project;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import com.bancika.gerberwriter.DataLayer;
|
||||
import com.bancika.gerberwriter.Point;
|
||||
import com.bancika.gerberwriter.path.MoveTo;
|
||||
import com.bancika.gerberwriter.path.Path;
|
||||
|
||||
public class GerberPathRenderer {
|
||||
|
||||
public static void drawComponent(Project currentProject, GerberG2DWrapper g2d, IDIYComponent<?> c,
|
||||
boolean outlineMode) {
|
||||
IGerberComponent gerberComponent = (IGerberComponent) c;
|
||||
g2d.startedDrawingComponent();
|
||||
if (gerberComponent instanceof IGerberComponentCustom) {
|
||||
IGerberComponentCustom gerberComponentCustom = (IGerberComponentCustom) gerberComponent;
|
||||
gerberComponentCustom.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d, g2d);
|
||||
} else if (gerberComponent instanceof IGerberComponentSimple) {
|
||||
IGerberComponentSimple gerberComponentSimple = (IGerberComponentSimple) gerberComponent;
|
||||
g2d.startGerberOutput(gerberComponentSimple.getGerberLayer(),
|
||||
gerberComponentSimple.getGerberFunction(), gerberComponentSimple.isGerberNegative());
|
||||
c.draw(g2d, ComponentState.NORMAL, outlineMode, currentProject, g2d);
|
||||
g2d.stopGerberOutput();
|
||||
}
|
||||
}
|
||||
|
||||
public static void outputPathArea(PathIterator pathIterator, DataLayer dataLayer, double d,
|
||||
boolean isNegative, String function) {
|
||||
List<PathWithNegative> outputPath =
|
||||
approximatePathWithPolygonPaths(pathIterator, d, isNegative);
|
||||
outputPath.forEach(p -> dataLayer.addRegion(p.path, function, p.negative));
|
||||
}
|
||||
|
||||
public static void outputPathOutline(PathIterator pathIterator, DataLayer dataLayer, double d,
|
||||
boolean isNegative, String function, double width) {
|
||||
List<PathWithNegative> outputPath =
|
||||
approximatePathWithPolygonPaths(pathIterator, d, isNegative);
|
||||
outputPath.forEach(p -> dataLayer.addTracesPath(p.path, width * SizeUnit.px.getFactor(),
|
||||
function, p.negative));
|
||||
}
|
||||
|
||||
public static List<PathWithNegative> approximatePathWithPolygonPaths(PathIterator pathIterator,
|
||||
double d, boolean isNegative) {
|
||||
// List<PathWithNegative> convert = PathIteratorConverter.convert(pathIterator, d, isNegative);
|
||||
// convert.forEach(c -> outputAction.write(c.path, c.negative));
|
||||
// if (true)
|
||||
// return;
|
||||
List<PathWithNegative> results = new ArrayList<PathWithNegative>();
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
Path path = null;
|
||||
Path2D lastPath = null;
|
||||
Area lastArea = null;
|
||||
while (!pathIterator.isDone()) {
|
||||
double[] coords = new double[6];
|
||||
int operation = pathIterator.currentSegment(coords);
|
||||
// int windingRule = pathIterator.getWindingRule();
|
||||
switch (operation) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
path = new Path();
|
||||
lastPath = new Path2D.Double();
|
||||
lastPath.moveTo(coords[0], coords[1]);
|
||||
path.moveTo(
|
||||
new Point(coords[0] * SizeUnit.px.getFactor(), coords[1] * SizeUnit.px.getFactor()));
|
||||
x = coords[0];
|
||||
y = coords[1];
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
lastPath.lineTo(coords[0], coords[1]);
|
||||
path.lineTo(
|
||||
new Point(coords[0] * SizeUnit.px.getFactor(), coords[1] * SizeUnit.px.getFactor()));
|
||||
x = coords[0];
|
||||
y = coords[1];
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
// safety check, do it better
|
||||
if (!path.isContour()) {
|
||||
path.lineTo(((MoveTo) path.getOperators().get(0)).getTo());
|
||||
}
|
||||
lastPath.closePath();
|
||||
if (lastArea == null) {
|
||||
results.add(new PathWithNegative(path, lastPath));
|
||||
} else {
|
||||
lastArea.intersect(new Area(lastPath));
|
||||
results.add(new PathWithNegative(path, lastPath));
|
||||
}
|
||||
lastArea = new Area(lastPath);
|
||||
path = null;
|
||||
break;
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
lastPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
|
||||
CubicCurve2D curve1 = new CubicCurve2D.Double(x, y, coords[0], coords[1], coords[2],
|
||||
coords[3], coords[4], coords[5]);
|
||||
subdivide(curve1, path, d);
|
||||
x = coords[4];
|
||||
y = coords[5];
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
lastPath.curveTo(coords[0], coords[1], (coords[0] + 2 * coords[2]) / 3,
|
||||
(coords[3] + 2 * coords[1]) / 3, coords[2], coords[3]);
|
||||
QuadCurve2D curve2 =
|
||||
new QuadCurve2D.Double(x, y, coords[0], coords[1], coords[2], coords[3]);
|
||||
subdivide(curve2, path, d);
|
||||
x = coords[2];
|
||||
y = coords[3];
|
||||
break;
|
||||
}
|
||||
pathIterator.next();
|
||||
}
|
||||
// check any leftover open path
|
||||
if (path != null) {
|
||||
results.add(new PathWithNegative(path, lastPath));
|
||||
}
|
||||
|
||||
results.sort(Comparator.comparing(a -> a.getArea(), Comparator.reverseOrder()));
|
||||
|
||||
assignNegativeFlags(results, isNegative);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public static void assignNegativeFlags(List<PathWithNegative> paths, boolean initialNegative) {
|
||||
if (paths == null || paths.isEmpty())
|
||||
return;
|
||||
|
||||
// Assume the list is already sorted with larger (outer) paths first.
|
||||
// Set the first one to the given initial value.
|
||||
paths.get(0).negative = initialNegative;
|
||||
|
||||
// For each subsequent path...
|
||||
for (int i = 1; i < paths.size(); i++) {
|
||||
boolean foundParent = false;
|
||||
// Check larger paths (starting from the closest; i.e. immediately before i)
|
||||
for (int j = i - 1; j >= 0; j--) {
|
||||
if (paths.get(j).contains(paths.get(i).currentPoint)) {
|
||||
// If candidate is inside parent, assign the opposite polarity.
|
||||
paths.get(i).negative = !paths.get(j).negative;
|
||||
foundParent = true;
|
||||
break; // stop after the first containing parent is found
|
||||
}
|
||||
}
|
||||
// If no parent was found, assign the initial value.
|
||||
if (!foundParent) {
|
||||
paths.get(i).negative = initialNegative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void subdivide(CubicCurve2D curve, Path path, double d) {
|
||||
if (curve.getFlatness() < d / 3 || new Point2D.Double(curve.getX1(), curve.getY1())
|
||||
.distance(curve.getX2(), curve.getY2()) < d) {
|
||||
|
||||
path.lineTo(new Point(curve.getX2() * SizeUnit.px.getFactor(),
|
||||
curve.getY2() * SizeUnit.px.getFactor()));
|
||||
return;
|
||||
}
|
||||
CubicCurve2D left = new CubicCurve2D.Double();
|
||||
CubicCurve2D right = new CubicCurve2D.Double();
|
||||
curve.subdivide(left, right);
|
||||
subdivide(left, path, d);
|
||||
subdivide(right, path, d);
|
||||
}
|
||||
|
||||
private static void subdivide(QuadCurve2D curve, Path path, double d) {
|
||||
if (curve.getFlatness() < d / 3 || new Point2D.Double(curve.getX1(), curve.getY1())
|
||||
.distance(curve.getX2(), curve.getY2()) < d) {
|
||||
|
||||
path.lineTo(new Point(curve.getX2() * SizeUnit.px.getFactor(),
|
||||
curve.getY2() * SizeUnit.px.getFactor()));
|
||||
return;
|
||||
}
|
||||
QuadCurve2D left = new QuadCurve2D.Double();
|
||||
QuadCurve2D right = new QuadCurve2D.Double();
|
||||
curve.subdivide(left, right);
|
||||
subdivide(left, path, d);
|
||||
subdivide(right, path, d);
|
||||
}
|
||||
|
||||
public static void renderShapeToPNG(Shape shape, String outputPath) throws IOException {
|
||||
// 1. Determine the bounding box of the shape.
|
||||
Rectangle2D bounds = shape.getBounds2D();
|
||||
|
||||
// Ensure we have a positive width/height.
|
||||
// (You may want to add padding or checks if shape is empty or negative sized.)
|
||||
int width = (int) Math.ceil(bounds.getWidth());
|
||||
int height = (int) Math.ceil(bounds.getHeight());
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException("Shape has invalid bounds: " + bounds);
|
||||
}
|
||||
|
||||
// 2. Create a BufferedImage (RGB) with the required dimensions.
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// 3. Draw the shape.
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
try {
|
||||
// Enable anti-aliasing if desired
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
// White background
|
||||
g2d.setColor(Color.WHITE);
|
||||
g2d.fillRect(0, 0, width, height);
|
||||
|
||||
// Translate the graphics context so the shape appears at (0,0)
|
||||
g2d.translate(-bounds.getX(), -bounds.getY());
|
||||
|
||||
// Draw the shape in black
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.fill(shape);
|
||||
} finally {
|
||||
g2d.dispose();
|
||||
}
|
||||
|
||||
// 4. Write the result to a PNG file
|
||||
ImageIO.write(image, "png", new File(outputPath));
|
||||
}
|
||||
|
||||
private static class PathWithNegative {
|
||||
|
||||
Path path;
|
||||
boolean negative;
|
||||
Area lastPath;
|
||||
Point2D currentPoint;
|
||||
|
||||
public PathWithNegative(Path path, Path2D lastPath) {
|
||||
this.path = path;
|
||||
this.lastPath = new Area(lastPath);
|
||||
currentPoint = lastPath.getCurrentPoint();
|
||||
}
|
||||
|
||||
double getArea() {
|
||||
return lastPath.getBounds2D().getWidth() * lastPath.getBounds2D().getHeight();
|
||||
}
|
||||
|
||||
boolean contains(Point2D point) {
|
||||
return lastPath.contains(point);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
public enum GerberRenderMode {
|
||||
Normal, Outline
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
public interface IGerberBoard {
|
||||
|
||||
Rectangle2D getBoardRectangle();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
public interface IGerberComponent {
|
||||
|
||||
default Set<GerberRenderMode> getGerberRenderModes() {
|
||||
return EnumSet.of(GerberRenderMode.Outline);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import org.diylc.core.ComponentState;
|
||||
import org.diylc.core.IDrawingObserver;
|
||||
import org.diylc.core.Project;
|
||||
|
||||
public interface IGerberComponentCustom extends IGerberComponent {
|
||||
|
||||
void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
|
||||
IDrawingObserver drawingObserver, IGerberDrawingObserver gerberDrawingObserver);
|
||||
|
||||
@Override
|
||||
default Set<GerberRenderMode> getGerberRenderModes() {
|
||||
return EnumSet.of(GerberRenderMode.Normal);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
public interface IGerberComponentSimple extends IGerberComponent {
|
||||
|
||||
default GerberLayer getGerberLayer() {
|
||||
return GerberLayer.SilkscreenTop;
|
||||
}
|
||||
|
||||
default String getGerberFunction() {
|
||||
return "ComponentOutline,Footprint";
|
||||
}
|
||||
|
||||
default boolean isGerberNegative() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
public interface IGerberDrawingObserver {
|
||||
|
||||
void startGerberOutput(GerberLayer layer, String function, boolean negative);
|
||||
|
||||
void setGerberFunction(GerberLayer layer, String function);
|
||||
|
||||
void setGerberNegative(GerberLayer layer, boolean negative);
|
||||
|
||||
void stopGerberOutput(GerberLayer layer);
|
||||
|
||||
void setApproximationToleranceOverride(double tolerance);
|
||||
|
||||
void stopGerberOutput();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.diylc.core.gerber;
|
||||
|
||||
import com.bancika.gerberwriter.path.Path;
|
||||
|
||||
public interface IGerberOutput {
|
||||
|
||||
void write(Path path, boolean negative);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2018 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.images;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
|
||||
/**
|
||||
* Loads image resources as Icons.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public enum IconLoader {
|
||||
|
||||
Delete("delete.png"), Add("add.png"), FolderOut("folder_out.png"), Garbage("garbage.png"), DiskBlue("disk_blue.png"), SaveAs(
|
||||
"save_as.png"), Exit("exit.png"), DocumentPlainYellow("document_plain_yellow.png"), PhotoScenery(
|
||||
"photo_scenery.png"), LightBulbOn("lightbulb_on.png"), LightBulbOff("lightbulb_off.png"), NotebookAdd(
|
||||
"notebook_add.png"), FormGreen("form_green.png"), Gears("gears.png"), About("about.png"), WindowColors(
|
||||
"window_colors.png"), WindowGear("window_gear.png"), NavigateCheck("navigate_check.png"), Undo("undo.png"), Error(
|
||||
"error.png"), Warning("warning.png"), ZoomSmall("zoom_small.png"), MoveSmall("move_small.png"), Print("print.png"), PDF(
|
||||
"pdf.png"), Excel("excel.png"), CSV("csv.png"), HTML("html.png"), Image("image.png"), Cut("cut.png"), Copy(
|
||||
"copy.png"), Paste("paste.png"), Selection("selection.png"), BOM("bom.png"), BlackBoard("blackboard.png"), IdCard(
|
||||
"id_card.png"), IdCardAdd("id_card_add.png"), Chest("chest.png"), Upload("upload.png"), Wrench("wrench.png"), Group(
|
||||
"group.png"), Ungroup("ungroup.png"), TraceMask("trace_mask.png"), Faq("faq.png"), Component("component.png"), Plugin(
|
||||
"plugin.png"), Manual("manual.png"), Donate("donate.png"), Bug("bug.png"), IconLarge("icon_large.png"), IconMedium(
|
||||
"icon_medium.png"), IconSmall("icon_small.png"), DocumentEdit("document_edit.png"), EditComponent(
|
||||
"edit_component.png"), Size("size.png"), Front("front.png"), Back("back.png"), Pens("pens.png"), Sort("sort.png"), ElementsSelection(
|
||||
"elements_selection.png"), Schaller("schaller.png");
|
||||
|
||||
protected String name;
|
||||
|
||||
private IconLoader(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Icon getIcon() {
|
||||
java.net.URL imgURL = getClass().getResource(name);
|
||||
if (imgURL != null) {
|
||||
return new ImageIcon(imgURL, name);
|
||||
} else {
|
||||
System.err.println("Couldn't find file: " + name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Image getImage() {
|
||||
BufferedImage img = null;
|
||||
try {
|
||||
img = ImageIO.read(getClass().getResourceAsStream(name));
|
||||
} catch (IOException e) {
|
||||
System.err.println("Couldn't find file: " + name);
|
||||
}
|
||||
return img;
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 875 B |
|
After Width: | Height: | Size: 729 B |
|
After Width: | Height: | Size: 749 B |
|
After Width: | Height: | Size: 736 B |
|
After Width: | Height: | Size: 707 B |
|
After Width: | Height: | Size: 714 B |
|
After Width: | Height: | Size: 993 B |