Added "Find" functionality that locates and selects component(s)

matching the search text
This commit is contained in:
bancika
2020-04-13 14:54:59 +02:00
parent 8d188f0038
commit d720f73887
11 changed files with 230 additions and 7 deletions
@@ -102,5 +102,9 @@ public enum EventType {
/**
* Called to update the status message. New status message is passed as a first parameter.
*/
STATUS_MESSAGE_CHANGED;
STATUS_MESSAGE_CHANGED,
/**
* Signals the listeners to scroll to selection.
*/
SCROLL_TO;
}
@@ -113,5 +113,12 @@ public interface ISelectionProcessor {
* @param yOffset
* @param includeStuckComponents
*/
void nudgeSelection(Size xOffset, Size yOffset, boolean includeStuckComponents);
void nudgeSelection(Size xOffset, Size yOffset, boolean includeStuckComponents);
/**
* Selects components that match the criteria.
*
* @param criteria
*/
void selectMatching(String criteria);
}
@@ -32,5 +32,25 @@ public enum Orientation {
} 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());
}
}
@@ -1003,6 +1003,19 @@ public class Presenter implements IPlugInPort {
messageDispatcher.dispatchMessage(EventType.REPAINT);
drawingManager.clearContinuityArea();
}
@Override
public void selectMatching(String criteria) {
Set<IDIYComponent<?>> matching = new HashSet<IDIYComponent<?>>();
for (IDIYComponent<?> c : currentProject.getComponents()) {
if ((c.getName() != null && c.getName().toLowerCase().matches(criteria.toLowerCase())) ||
(c.getValueForDisplay() != null && c.getValueForDisplay().toLowerCase().matches(criteria.toLowerCase())))
matching.add(c);
}
updateSelection(matching);
messageDispatcher.dispatchMessage(EventType.REPAINT);
messageDispatcher.dispatchMessage(EventType.SCROLL_TO, getSelectionBounds(true));
}
@Override
public VersionNumber getCurrentVersionNumber() {
@@ -1924,7 +1937,7 @@ public class Presenter implements IPlugInPort {
if (ConfigurationManager.getInstance().readBoolean(IPlugInPort.STICKY_POINTS_KEY, true)) {
includeStuckComponents(controlPointMap);
}
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents, controlPointMap.keySet());
messageDispatcher.dispatchMessage(EventType.SELECTION_CHANGED, selectedComponents, controlPointMap.keySet());
}
private static boolean useNetlistForExpandSelection = false;
@@ -2934,6 +2934,10 @@
<releaseDate>2020-04-09 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added "Find" functionality that locates and selects component(s) matching the search text</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added "Tag Strip" component for point-to-point layouts</description>
Binary file not shown.
@@ -73,13 +73,14 @@ import org.diylc.swing.gui.DialogFactory;
import org.diylc.swing.gui.editor.PropertyEditorDialog;
import org.diylc.swing.plugins.config.ConfigPlugin;
import org.diylc.swing.plugins.edit.ComponentTransferable;
import org.diylc.swing.plugins.edit.FindDialog;
import org.diylc.swing.plugins.file.BomDialog;
import org.diylc.swing.plugins.file.FileFilterEnum;
import org.diylc.swingframework.ButtonDialog;
import org.diylc.swingframework.CheckBoxListDialog;
import org.diylc.swingframework.IDrawingProvider;
import org.diylc.swingframework.export.DrawingExporter;
import org.diylc.swingframework.TextDialog;
import org.diylc.swingframework.export.DrawingExporter;
import org.diylc.utils.BomEntry;
import com.thoughtworks.xstream.XStream;
@@ -231,6 +232,10 @@ public class ActionFactory {
public NudgeAction createNudgeAction(IPlugInPort plugInPort) {
return new NudgeAction(plugInPort);
}
public FindAction createFindAction(IPlugInPort plugInPort, ISwingUI swingUI) {
return new FindAction(plugInPort, swingUI);
}
// Config actions.
@@ -1545,6 +1550,38 @@ public class ActionFactory {
plugInPort.bringSelectionToFront();
}
}
public static class FindAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private IPlugInPort plugInPort;
private ISwingUI swingUI;
public FindAction(IPlugInPort plugInPort, ISwingUI swingUI) {
super();
this.plugInPort = plugInPort;
this.swingUI = swingUI;
putValue(AbstractAction.NAME, "Find");
putValue(AbstractAction.SMALL_ICON, IconLoader.SearchBox.getIcon());
putValue(AbstractAction.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F, ActionEvent.CTRL_MASK));
}
@Override
public void actionPerformed(ActionEvent e) {
LOG.info("Find triggered");
FindDialog dialog = DialogFactory.getInstance().createFindDialog();
dialog.setVisible(true);
if (dialog.getSelectedButtonCaption() == FindDialog.OK) {
String criteria = dialog.getCriteria();
plugInPort.selectMatching(criteria);
if (plugInPort.getSelectedComponents().size() == 0) {
swingUI.showMessage("No matching components found.", "Find", ISwingUI.INFORMATION_MESSAGE);
}
}
}
}
public static class ConfigAction extends AbstractAction {
@@ -36,6 +36,7 @@ import org.diylc.swing.plugins.cloud.view.ChangePasswordDialog;
import org.diylc.swing.plugins.cloud.view.LoginDialog;
import org.diylc.swing.plugins.cloud.view.UploadDialog;
import org.diylc.swing.plugins.cloud.view.UserEditDialog;
import org.diylc.swing.plugins.edit.FindDialog;
import org.diylc.swing.plugins.file.BomDialog;
import org.diylc.swingframework.AboutDialog;
import org.diylc.swingframework.IFileChooserAccessory;
@@ -196,6 +197,11 @@ public class DialogFactory {
LoginDialog dialog = new LoginDialog(mainFrame);
return dialog;
}
public FindDialog createFindDialog() {
FindDialog dialog = new FindDialog(mainFrame);
return dialog;
}
public UploadDialog createUploadDialog(JFrame ownerFrame, IPlugInPort plugInPort, String[] categories,
boolean isUpdate) {
@@ -706,7 +706,7 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
@Override
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, EventType.SCROLL_TO);
}
@SuppressWarnings("incomplete-switch")
@@ -759,6 +759,12 @@ public class CanvasPlugin implements IPlugIn, ClipboardOwner {
}
});
break;
case SCROLL_TO:
Rectangle visibleRect2 = canvasPanel.getVisibleRect();
Rectangle2D targetRect = (Rectangle2D) params[0];
canvasPanel.scrollRectToVisible(new Rectangle((int)(targetRect.getCenterX() - visibleRect2.width / 2),
(int)(targetRect.getCenterY() - visibleRect2.height / 2), visibleRect2.width, visibleRect2.height));
break;
}
// }
// });
@@ -74,7 +74,8 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
private ActionFactory.RotateSelectionAction rotateClockwiseAction;
private ActionFactory.RotateSelectionAction rotateCounterClockwiseAction;
private ActionFactory.MirrorSelectionAction mirrorHorizontallyAction;
private ActionFactory.MirrorSelectionAction mirrorVerticallyAction;
private ActionFactory.MirrorSelectionAction mirrorVerticallyAction;
private ActionFactory.FindAction findAction;
private UndoHandler<Project> undoHandler;
@@ -261,6 +262,12 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
ActionFactory.getInstance().createMirrorSelectionAction(plugInPort, IComponentTransformer.VERTICAL);
}
return mirrorVerticallyAction;
}
public ActionFactory.FindAction getFindAction() {
if (findAction == null)
findAction = ActionFactory.getInstance().createFindAction(plugInPort, swingUI);
return findAction;
}
@Override
@@ -276,7 +283,8 @@ public class EditMenuPlugin implements IPlugIn, ClipboardOwner {
swingUI.injectMenuAction(getCopyAction(), EDIT_TITLE);
swingUI.injectMenuAction(getPasteAction(), EDIT_TITLE);
swingUI.injectMenuAction(getDuplicateAction(), EDIT_TITLE);
swingUI.injectMenuAction(null, EDIT_TITLE);
swingUI.injectMenuAction(null, EDIT_TITLE);
swingUI.injectMenuAction(getFindAction(), EDIT_TITLE);
swingUI.injectMenuAction(actionFactory.createSelectAllAction(plugInPort), EDIT_TITLE);
swingUI.injectMenuAction(getEditSelectionAction(), EDIT_TITLE);
swingUI.injectMenuAction(getDeleteSelectionAction(), EDIT_TITLE);
@@ -0,0 +1,118 @@
/*
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.swing.plugins.edit;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.diylc.swingframework.ButtonDialog;
public class FindDialog extends ButtonDialog {
private static final long serialVersionUID = 1L;
private JPanel mainPanel;
private JTextField criteriaField;
private String criteria;
public FindDialog(JFrame owner) {
super(owner, "Find", new String[] {OK, CANCEL});
setMinimumSize(new Dimension(240, 32));
layoutGui();
refreshState();
}
public String getCriteria() {
return criteria;
}
@Override
protected JComponent getMainComponent() {
if (mainPanel == null) {
mainPanel = new JPanel(new GridBagLayout());
mainPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.NONE;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.gridx = 0;
gbc.gridy = 0;
mainPanel.add(new JLabel("Look for:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1;
gbc.gridy = 0;
mainPanel.add(getCriteriaField(), gbc);
}
return mainPanel;
}
private void refreshState() {
this.criteria = getCriteriaField().getText();
JButton okButton = getButton(OK);
okButton.setEnabled(this.criteria.length() > 0);
}
private JTextField getCriteriaField() {
if (criteriaField == null) {
criteriaField = new JTextField();
criteriaField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
refreshState();
}
@Override
public void insertUpdate(DocumentEvent e) {
refreshState();
}
@Override
public void changedUpdate(DocumentEvent e) {
refreshState();
}
});
}
return criteriaField;
}
}