Expand selection feature, useful for debugging

Limit length of text in the status bar using "and X more" suffix
This commit is contained in:
bancika
2012-02-26 03:54:12 +00:00
parent 4ee7381959
commit dd9e9f054c
11 changed files with 234 additions and 7 deletions
@@ -3,6 +3,7 @@ package org.diylc.common;
import java.awt.Point; import java.awt.Point;
import java.util.List; import java.util.List;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
public interface ISelectionProcessor { public interface ISelectionProcessor {
@@ -32,6 +33,14 @@ public interface ISelectionProcessor {
*/ */
List<IDIYComponent<?>> findComponentsAt(Point point); List<IDIYComponent<?>> findComponentsAt(Point point);
/**
* 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. * Selects all components in the project.
*/ */
@@ -0,0 +1,8 @@
package org.diylc.core;
public enum ExpansionMode {
ALL,
SAME_TYPE,
IMMEDIATE,
}
@@ -37,6 +37,7 @@ import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
import org.diylc.common.PropertyWrapper; import org.diylc.common.PropertyWrapper;
import org.diylc.components.connectivity.SolderPad; import org.diylc.components.connectivity.SolderPad;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IView; import org.diylc.core.IView;
import org.diylc.core.Project; import org.diylc.core.Project;
@@ -55,7 +56,7 @@ public class Presenter implements IPlugInPort {
private static final Logger LOG = Logger.getLogger(Presenter.class); private static final Logger LOG = Logger.getLogger(Presenter.class);
public static final VersionNumber CURRENT_VERSION = new VersionNumber(3, 2, 0); public static final VersionNumber CURRENT_VERSION = new VersionNumber(3, 3, 0);
public static final String DEFAULTS_KEY_PREFIX = "default."; public static final String DEFAULTS_KEY_PREFIX = "default.";
public static final List<IDIYComponent<?>> EMPTY_SELECTION = Collections.emptyList(); public static final List<IDIYComponent<?>> EMPTY_SELECTION = Collections.emptyList();
@@ -1078,6 +1079,7 @@ public class Presenter implements IPlugInPort {
@Override @Override
public void refresh() { public void refresh() {
LOG.info("refresh()");
messageDispatcher.dispatchMessage(EventType.REPAINT); messageDispatcher.dispatchMessage(EventType.REPAINT);
} }
@@ -1093,6 +1095,7 @@ public class Presenter implements IPlugInPort {
@Override @Override
public void renumberSelectedComponents(final boolean xAxisFirst) { public void renumberSelectedComponents(final boolean xAxisFirst) {
LOG.info("renumberSelectedComponents(" + xAxisFirst + ")");
if (getSelectedComponents().isEmpty()) { if (getSelectedComponents().isEmpty()) {
return; return;
} }
@@ -1183,6 +1186,66 @@ public class Presenter implements IPlugInPort {
controlPointMap.keySet()); controlPointMap.keySet());
} }
@Override
public void expandSelection(ExpansionMode expansionMode) {
List<IDIYComponent<?>> newSelection = new ArrayList<IDIYComponent<?>>(
this.selectedComponents);
// Find control points of all selected components and all types
Set<String> selectedNamePrefixes = new HashSet<String>();
if (expansionMode == ExpansionMode.SAME_TYPE) {
for (IDIYComponent<?> component : getSelectedComponents()) {
selectedNamePrefixes.add(ComponentProcessor.getInstance().extractComponentTypeFrom(
(Class<? extends IDIYComponent<?>>) component.getClass()).getNamePrefix());
}
}
// Now try to find components that intersect with at least one component
// in the pool.
for (IDIYComponent<?> component : getCurrentProject().getComponents()) {
// Skip already selected components or ones that cannot be stuck to
// other components.
Area area = drawingManager.getComponentArea(component);
if (newSelection.contains(component) || !component.isControlPointSticky(0) || area == null)
continue;
boolean matches = false;
for (IDIYComponent<?> selectedComponent : this.selectedComponents) {
Area selectedArea = drawingManager.getComponentArea(selectedComponent);
if (selectedArea == null)
continue;
Area intersection = new Area(area);
intersection.intersect(selectedArea);
if (!intersection.isEmpty()) {
matches = true;
break;
}
}
if (matches) {
switch (expansionMode) {
case ALL:
case IMMEDIATE:
newSelection.add(component);
break;
case SAME_TYPE:
if (selectedNamePrefixes.contains(ComponentProcessor.getInstance()
.extractComponentTypeFrom(
(Class<? extends IDIYComponent<?>>) component.getClass())
.getNamePrefix())) {
newSelection.add(component);
}
break;
}
}
}
int oldSize = this.getSelectedComponents().size();
updateSelection(newSelection);
// Go deeper if possible.
if (newSelection.size() > oldSize && expansionMode != ExpansionMode.IMMEDIATE) {
expandSelection(expansionMode);
}
messageDispatcher.dispatchMessage(EventType.REPAINT);
}
/** /**
* Removes all the groups that contain at least one of the specified * Removes all the groups that contain at least one of the specified
* components. * components.
@@ -31,7 +31,8 @@ public enum IconLoader {
"donate.png"), Bug("bug.png"), IconLarge("icon_large.png"), IconMedium( "donate.png"), Bug("bug.png"), IconLarge("icon_large.png"), IconMedium(
"icon_medium.png"), IconSmall("icon_small.png"), DocumentEdit("document_edit.png"), EditComponent( "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( "edit_component.png"), Size("size.png"), Front("front.png"), Back("back.png"), Pens(
"pens.png"), Sort("sort.png"), ElementsSelection("elements_selection.png"); "pens.png"), Sort("sort.png"), ElementsSelection("elements_selection.png"), BranchAdd(
"branch_add.png");
protected String name; protected String name;
Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

@@ -16,6 +16,7 @@ import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
import org.diylc.common.ITask; import org.diylc.common.ITask;
import org.diylc.common.PropertyWrapper; import org.diylc.common.PropertyWrapper;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IView; import org.diylc.core.IView;
import org.diylc.core.Theme; import org.diylc.core.Theme;
@@ -128,6 +129,11 @@ public class ActionFactory {
return new DeleteSelectionAction(plugInPort); return new DeleteSelectionAction(plugInPort);
} }
public ExpandSelectionAction createExpandSelectionAction(IPlugInPort plugInPort,
ExpansionMode expansionMode) {
return new ExpandSelectionAction(plugInPort, expansionMode);
}
public SendToBackAction createSendToBackAction(IPlugInPort plugInPort) { public SendToBackAction createSendToBackAction(IPlugInPort plugInPort) {
return new SendToBackAction(plugInPort); return new SendToBackAction(plugInPort);
} }
@@ -142,11 +148,11 @@ public class ActionFactory {
boolean defaultValue) { boolean defaultValue) {
return new ConfigAction(plugInPort, title, configKey, defaultValue); return new ConfigAction(plugInPort, title, configKey, defaultValue);
} }
public ThemeAction createThemeAction(IPlugInPort plugInPort, Theme theme) { public ThemeAction createThemeAction(IPlugInPort plugInPort, Theme theme) {
return new ThemeAction(plugInPort, theme); return new ThemeAction(plugInPort, theme);
} }
public RenumberAction createRenumberAction(IPlugInPort plugInPort, boolean xAxisFirst) { public RenumberAction createRenumberAction(IPlugInPort plugInPort, boolean xAxisFirst) {
return new RenumberAction(plugInPort, xAxisFirst); return new RenumberAction(plugInPort, xAxisFirst);
} }
@@ -756,6 +762,40 @@ public class ActionFactory {
} }
} }
public static class ExpandSelectionAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private IPlugInPort plugInPort;
private ExpansionMode expansionMode;
public ExpandSelectionAction(IPlugInPort plugInPort, ExpansionMode expansionMode) {
super();
this.plugInPort = plugInPort;
this.expansionMode = expansionMode;
switch (expansionMode) {
case ALL:
putValue(AbstractAction.NAME, "All Connected");
break;
case IMMEDIATE:
putValue(AbstractAction.NAME, "Immediate Only");
break;
case SAME_TYPE:
putValue(AbstractAction.NAME, "Same Type Only");
break;
default:
break;
}
}
@Override
public void actionPerformed(ActionEvent e) {
LOG.info("Expand Selection triggered: " + expansionMode);
plugInPort.expandSelection(expansionMode);
}
}
public static class SendToBackAction extends AbstractAction { public static class SendToBackAction extends AbstractAction {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -846,7 +886,7 @@ public class ActionFactory {
plugInPort.setSelectedTheme(theme); plugInPort.setSelectedTheme(theme);
} }
} }
public static class RenumberAction extends AbstractAction { public static class RenumberAction extends AbstractAction {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@@ -29,6 +29,7 @@ import org.diylc.common.BadPositionException;
import org.diylc.common.EventType; import org.diylc.common.EventType;
import org.diylc.common.IPlugIn; import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
import org.diylc.core.ExpansionMode;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.measures.Size; import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit; import org.diylc.core.measures.SizeUnit;
@@ -49,6 +50,7 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
private CanvasPanel canvasPanel; private CanvasPanel canvasPanel;
private JPopupMenu popupMenu; private JPopupMenu popupMenu;
private JMenu selectionMenu; private JMenu selectionMenu;
private JMenu expandMenu;
private ActionFactory.CutAction cutAction; private ActionFactory.CutAction cutAction;
private ActionFactory.CopyAction copyAction; private ActionFactory.CopyAction copyAction;
@@ -59,6 +61,9 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
private ActionFactory.UngroupAction ungroupAction; private ActionFactory.UngroupAction ungroupAction;
private ActionFactory.SendToBackAction sendToBackAction; private ActionFactory.SendToBackAction sendToBackAction;
private ActionFactory.BringToFrontAction bringToFrontAction; private ActionFactory.BringToFrontAction bringToFrontAction;
private ActionFactory.ExpandSelectionAction expandSelectionAllAction;
private ActionFactory.ExpandSelectionAction expandSelectionImmediateAction;
private ActionFactory.ExpandSelectionAction expandSelectionSameTypeAction;
private IPlugInPort plugInPort; private IPlugInPort plugInPort;
private ISwingUI swingUI; private ISwingUI swingUI;
@@ -104,6 +109,9 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
} }
getEditSelectionAction().setEnabled(enabled); getEditSelectionAction().setEnabled(enabled);
getDeleteSelectionAction().setEnabled(enabled); getDeleteSelectionAction().setEnabled(enabled);
getExpandSelectionAllAction().setEnabled(enabled);
getExpandSelectionImmediateAction().setEnabled(enabled);
getExpandSelectionSameTypeAction().setEnabled(enabled);
getGroupAction().setEnabled(enabled); getGroupAction().setEnabled(enabled);
getUngroupAction().setEnabled(enabled); getUngroupAction().setEnabled(enabled);
getSendToBackAction().setEnabled(enabled); getSendToBackAction().setEnabled(enabled);
@@ -193,6 +201,7 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
popupMenu.add(getUngroupAction()); popupMenu.add(getUngroupAction());
popupMenu.add(getSendToBackAction()); popupMenu.add(getSendToBackAction());
popupMenu.add(getBringToFrontAction()); popupMenu.add(getBringToFrontAction());
popupMenu.add(getExpandMenu());
popupMenu.addSeparator(); popupMenu.addSeparator();
popupMenu.add(ActionFactory.getInstance().createEditProjectAction(plugInPort)); popupMenu.add(ActionFactory.getInstance().createEditProjectAction(plugInPort));
} }
@@ -207,6 +216,17 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
return selectionMenu; return selectionMenu;
} }
public JMenu getExpandMenu() {
if (expandMenu == null) {
expandMenu = new JMenu("Expand Selection");
expandMenu.setIcon(IconLoader.BranchAdd.getIcon());
expandMenu.add(getExpandSelectionAllAction());
expandMenu.add(getExpandSelectionImmediateAction());
expandMenu.add(getExpandSelectionSameTypeAction());
}
return expandMenu;
}
private void updateSelectionMenu(int x, int y) { private void updateSelectionMenu(int x, int y) {
getSelectionMenu().removeAll(); getSelectionMenu().removeAll();
for (IDIYComponent<?> component : plugInPort.findComponentsAt(new Point(x, y))) { for (IDIYComponent<?> component : plugInPort.findComponentsAt(new Point(x, y))) {
@@ -290,6 +310,30 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
return bringToFrontAction; return bringToFrontAction;
} }
public ActionFactory.ExpandSelectionAction getExpandSelectionAllAction() {
if (expandSelectionAllAction == null) {
expandSelectionAllAction = ActionFactory.getInstance().createExpandSelectionAction(
plugInPort, ExpansionMode.ALL);
}
return expandSelectionAllAction;
}
public ActionFactory.ExpandSelectionAction getExpandSelectionImmediateAction() {
if (expandSelectionImmediateAction == null) {
expandSelectionImmediateAction = ActionFactory.getInstance()
.createExpandSelectionAction(plugInPort, ExpansionMode.IMMEDIATE);
}
return expandSelectionImmediateAction;
}
public ActionFactory.ExpandSelectionAction getExpandSelectionSameTypeAction() {
if (expandSelectionSameTypeAction == null) {
expandSelectionSameTypeAction = ActionFactory.getInstance()
.createExpandSelectionAction(plugInPort, ExpansionMode.SAME_TYPE);
}
return expandSelectionSameTypeAction;
}
@Override @Override
public EnumSet<EventType> getSubscribedEventTypes() { public EnumSet<EventType> getSubscribedEventTypes() {
return EnumSet.of(EventType.PROJECT_LOADED, EventType.ZOOM_CHANGED, EventType.REPAINT); return EnumSet.of(EventType.PROJECT_LOADED, EventType.ZOOM_CHANGED, EventType.REPAINT);
@@ -13,6 +13,7 @@ import org.diylc.appframework.undo.UndoHandler;
import org.diylc.common.EventType; import org.diylc.common.EventType;
import org.diylc.common.IPlugIn; import org.diylc.common.IPlugIn;
import org.diylc.common.IPlugInPort; import org.diylc.common.IPlugInPort;
import org.diylc.core.ExpansionMode;
import org.diylc.core.Project; import org.diylc.core.Project;
import org.diylc.images.IconLoader; import org.diylc.images.IconLoader;
import org.diylc.swing.ActionFactory; import org.diylc.swing.ActionFactory;
@@ -22,6 +23,7 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
private static final String EDIT_TITLE = "Edit"; private static final String EDIT_TITLE = "Edit";
private static final String RENUMBER_TITLE = "Renumber Selection"; private static final String RENUMBER_TITLE = "Renumber Selection";
private static final String EXPAND_TITLE = "Expand Selection";
private IPlugInPort plugInPort; private IPlugInPort plugInPort;
private ISwingUI swingUI; private ISwingUI swingUI;
@@ -39,6 +41,9 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
private ActionFactory.BringToFrontAction bringToFrontAction; private ActionFactory.BringToFrontAction bringToFrontAction;
private ActionFactory.RenumberAction renumberXAxisAction; private ActionFactory.RenumberAction renumberXAxisAction;
private ActionFactory.RenumberAction renumberYAxisAction; private ActionFactory.RenumberAction renumberYAxisAction;
private ActionFactory.ExpandSelectionAction expandSelectionAllAction;
private ActionFactory.ExpandSelectionAction expandSelectionImmediateAction;
private ActionFactory.ExpandSelectionAction expandSelectionSameTypeAction;
private UndoHandler<Project> undoHandler; private UndoHandler<Project> undoHandler;
@@ -149,6 +154,30 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
return renumberYAxisAction; return renumberYAxisAction;
} }
public ActionFactory.ExpandSelectionAction getExpandSelectionAllAction() {
if (expandSelectionAllAction == null) {
expandSelectionAllAction = ActionFactory.getInstance().createExpandSelectionAction(
plugInPort, ExpansionMode.ALL);
}
return expandSelectionAllAction;
}
public ActionFactory.ExpandSelectionAction getExpandSelectionImmediateAction() {
if (expandSelectionImmediateAction == null) {
expandSelectionImmediateAction = ActionFactory.getInstance().createExpandSelectionAction(
plugInPort, ExpansionMode.IMMEDIATE);
}
return expandSelectionImmediateAction;
}
public ActionFactory.ExpandSelectionAction getExpandSelectionSameTypeAction() {
if (expandSelectionSameTypeAction == null) {
expandSelectionSameTypeAction = ActionFactory.getInstance().createExpandSelectionAction(
plugInPort, ExpansionMode.SAME_TYPE);
}
return expandSelectionSameTypeAction;
}
@Override @Override
public void connect(IPlugInPort plugInPort) { public void connect(IPlugInPort plugInPort) {
this.plugInPort = plugInPort; this.plugInPort = plugInPort;
@@ -173,6 +202,10 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
swingUI.injectSubmenu(RENUMBER_TITLE, IconLoader.Sort.getIcon(), EDIT_TITLE); swingUI.injectSubmenu(RENUMBER_TITLE, IconLoader.Sort.getIcon(), EDIT_TITLE);
swingUI.injectMenuAction(getRenumberXAxisAction(), RENUMBER_TITLE); swingUI.injectMenuAction(getRenumberXAxisAction(), RENUMBER_TITLE);
swingUI.injectMenuAction(getRenumberYAxisAction(), RENUMBER_TITLE); swingUI.injectMenuAction(getRenumberYAxisAction(), RENUMBER_TITLE);
swingUI.injectSubmenu(EXPAND_TITLE, IconLoader.BranchAdd.getIcon(), EDIT_TITLE);
swingUI.injectMenuAction(getExpandSelectionAllAction(), EXPAND_TITLE);
swingUI.injectMenuAction(getExpandSelectionImmediateAction(), EXPAND_TITLE);
swingUI.injectMenuAction(getExpandSelectionSameTypeAction(), EXPAND_TITLE);
swingUI.injectMenuAction(null, EDIT_TITLE); swingUI.injectMenuAction(null, EDIT_TITLE);
swingUI.injectMenuAction(actionFactory.createEditProjectAction(plugInPort), EDIT_TITLE); swingUI.injectMenuAction(actionFactory.createEditProjectAction(plugInPort), EDIT_TITLE);
@@ -209,6 +242,9 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
getEditSelectionAction().setEnabled(enabled); getEditSelectionAction().setEnabled(enabled);
getDeleteSelectionAction().setEnabled(enabled); getDeleteSelectionAction().setEnabled(enabled);
getGroupAction().setEnabled(enabled); getGroupAction().setEnabled(enabled);
getExpandSelectionAllAction().setEnabled(enabled);
getExpandSelectionImmediateAction().setEnabled(enabled);
getExpandSelectionSameTypeAction().setEnabled(enabled);
getUngroupAction().setEnabled(enabled); getUngroupAction().setEnabled(enabled);
getSendToBackAction().setEnabled(enabled); getSendToBackAction().setEnabled(enabled);
getBringToFrontAction().setEnabled(enabled); getBringToFrontAction().setEnabled(enabled);
@@ -261,10 +261,16 @@ public class StatusBar extends JPanel implements IPlugIn {
statusText = "<html>Drag control point(s) of " + formattedNames + "</html>"; statusText = "<html>Drag control point(s) of " + formattedNames + "</html>";
} else if (selectedComponentNames != null && !selectedComponentNames.isEmpty()) { } else if (selectedComponentNames != null && !selectedComponentNames.isEmpty()) {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(Utils.toCommaString(selectedComponentNames)); builder.append(Utils.toCommaString(selectedComponentNames.subList(0, 20)));
if (selectedComponentNames.size() > 20) {
builder.append(" and " + (selectedComponentNames.size() - 20) + " more");
}
if (!stuckComponentNames.isEmpty()) { if (!stuckComponentNames.isEmpty()) {
builder.append(" (hold <b>Ctrl</b> and drag to unstuck from "); builder.append(" (hold <b>Ctrl</b> and drag to unstuck from ");
builder.append(Utils.toCommaString(stuckComponentNames)); builder.append(Utils.toCommaString(stuckComponentNames.subList(0, 5)));
if (stuckComponentNames.size() > 5) {
builder.append(" and " + (stuckComponentNames.size() - 5) + " more");
}
builder.append(")"); builder.append(")");
} }
statusText = "<html>Selection: " + builder.toString() + "</html>"; statusText = "<html>Selection: " + builder.toString() + "</html>";
@@ -453,5 +453,25 @@
</changes> </changes>
<url>http://code.google.com/p/diy-layout-creator/downloads/list</url> <url>http://code.google.com/p/diy-layout-creator/downloads/list</url>
</com.diyfever.gui.update.Version> </com.diyfever.gui.update.Version>
<com.diyfever.gui.update.Version>
<versionNumber>
<major>3</major>
<minor>3</minor>
<build>0</build>
</versionNumber>
<releaseDate>2012-02-25 20:00:00.000 CET</releaseDate>
<name></name>
<changes>
<com.diyfever.gui.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Expand selection feature, useful for debugging</description>
</com.diyfever.gui.update.Change>
<com.diyfever.gui.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Limit length of text in the status bar using "and X more" suffix</description>
</com.diyfever.gui.update.Change>
</changes>
<url>http://code.google.com/p/diy-layout-creator/downloads/list</url>
</com.diyfever.gui.update.Version>
</a> </a>
</java.util.Arrays_-ArrayList> </java.util.Arrays_-ArrayList>