adds "copy to clipboard" to terminal dialog; closes #725

This commit is contained in:
hneemann 2021-04-29 12:33:15 +02:00
parent b20673c27e
commit 27bab3f80b
10 changed files with 356 additions and 36 deletions

View File

@ -60,6 +60,10 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
* The delete icon, also used from {@link de.neemann.digital.gui.components.terminal.TerminalDialog}
*/
public static final Icon ICON_DELETE = IconCreator.create("delete.png");
/**
* The copy icon, also used from {@link de.neemann.digital.gui.components.terminal.TerminalDialog}
*/
public static final Icon ICON_COPY = IconCreator.create("edit-copy.png");
private static final Icon ICON_UNDO = IconCreator.create("edit-undo.png");
private static final Icon ICON_REDO = IconCreator.create("edit-redo.png");
private static final ArrayList<Key> ATTR_LIST = new ArrayList<>();
@ -431,7 +435,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
}
private ToolTipAction createCopyAction(ShapeFactory shapeFactory) {
return new ToolTipAction(Lang.get("menu_copy")) {
return new ToolTipAction(Lang.get("menu_copy"), ICON_COPY) {
@Override
public void actionPerformed(ActionEvent e) {
ArrayList<Movable> elements = getSelectedElements(shapeFactory);

View File

@ -23,10 +23,7 @@ import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.datatransfer.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
@ -205,7 +202,7 @@ public class DataEditor extends JDialog {
int[] rows = table.getSelectedRows();
if (rows.length > 0) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(new DataTransferable(((MyTableModel) table.getModel()).toString(rows)), null);
clipboard.setContents(new StringSelection(((MyTableModel) table.getModel()).toString(rows)), null);
}
}
}.setAcceleratorCTRLplus('C').enableAcceleratorIn(table);
@ -529,30 +526,4 @@ public class DataEditor extends JDialog {
}
}
private static final class DataTransferable implements Transferable {
private final String data;
private DataTransferable(String data) {
this.data = data;
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.stringFlavor};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor == DataFlavor.stringFlavor;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (!isDataFlavorSupported(flavor))
throw new UnsupportedFlavorException(flavor);
return data;
}
}
}

View File

@ -12,6 +12,11 @@ import java.awt.event.WindowFocusListener;
/**
* If added to a window, the focus is transferred to the given window.
* <p>
* Should be attached to dialogs which offer no user interaction at all.
* In other words, all windows that exclusively display something.
* As soon as there are menus, buttons or similar, this listener should
* no longer be used.
*/
public class MoveFocusTo implements WindowFocusListener {
private final Window parent;

View File

@ -9,13 +9,14 @@ import de.neemann.digital.core.Model;
import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.gui.components.CircuitComponent;
import de.neemann.digital.gui.components.graphics.MoveFocusTo;
import de.neemann.digital.lang.Lang;
import de.neemann.gui.Screen;
import de.neemann.gui.ToolTipAction;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import static de.neemann.digital.gui.components.terminal.ConsoleTerminal.MAX_TERMINAL_STORED;
@ -58,6 +59,7 @@ public final class TerminalDialog extends JDialog {
width = attr.get(Keys.TERM_WIDTH);
textArea = new JTextArea(attr.get(Keys.TERM_HEIGHT), width);
textArea.setFont(new Font("monospaced", Font.PLAIN, Screen.getInstance().getFontSize()));
textArea.setEditable(false);
getContentPane().add(new JScrollPane(textArea));
JToolBar toolBar = new JToolBar();
@ -67,13 +69,20 @@ public final class TerminalDialog extends JDialog {
textArea.setText("");
}
}.setToolTip(Lang.get("menu_terminalDelete_tt")).createJButtonNoText());
ToolTipAction copyAction = new ToolTipAction(Lang.get("menu_copy"), CircuitComponent.ICON_COPY) {
@Override
public void actionPerformed(ActionEvent e) {
final Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(new StringSelection(textArea.getText()), null);
}
}.setToolTip(Lang.get("menu_copy_tt")).setAcceleratorCTRLplus('C');
toolBar.add(copyAction.createJButtonNoText());
copyAction.enableAcceleratorIn(textArea);
getContentPane().add(toolBar, BorderLayout.NORTH);
pack();
setLocationRelativeTo(null);
setLocationRelativeTo(parent);
setVisible(true);
addWindowFocusListener(new MoveFocusTo(parent));
}
/**

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1767,6 +1767,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig?</string>
<string name="menu_analyse_tt">Analyse der aktuellen Schaltung</string>
<string name="menu_cut">Ausschneiden</string>
<string name="menu_copy">Kopieren</string>
<string name="menu_copy_tt">In die Zwischenablage kopieren</string>
<string name="menu_custom">Benutzerdefiniert</string>
<string name="menu_library">Bibliothek</string>
<string name="menu_delete">Löschen</string>

View File

@ -1752,6 +1752,7 @@
<string name="menu_analyse_tt">Analyses the current circuit</string>
<string name="menu_cut">Cut</string>
<string name="menu_copy">Copy</string>
<string name="menu_copy_tt">Copy to clipboard</string>
<string name="menu_custom">Custom</string>
<string name="menu_library">Library</string>
<string name="menu_delete">Delete components</string>

328
src/main/svg/edit-copy.svg Normal file
View File

@ -0,0 +1,328 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="48px"
height="48px"
id="svg4198"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docbase="/home/tigert/cvs/freedesktop.org/tango-icon-theme/scalable/actions"
sodipodi:docname="edit-copy.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs4200">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 24 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="48 : 24 : 1"
inkscape:persp3d-origin="24 : 16 : 1"
id="perspective45"/>
<linearGradient
id="linearGradient15218">
<stop
style="stop-color:#f0f0ef;stop-opacity:1.0000000;"
offset="0.0000000"
id="stop15220"/>
<stop
id="stop2269"
offset="0.59928656"
style="stop-color:#e8e8e8;stop-opacity:1;"/>
<stop
id="stop2267"
offset="0.82758623"
style="stop-color:#ffffff;stop-opacity:1;"/>
<stop
style="stop-color:#d8d8d3;stop-opacity:1.0000000;"
offset="1.0000000"
id="stop15222"/>
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2259">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2261"/>
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2263"/>
</linearGradient>
<linearGradient
id="linearGradient2224">
<stop
style="stop-color:#7c7c7c;stop-opacity:1;"
offset="0"
id="stop2226"/>
<stop
style="stop-color:#b8b8b8;stop-opacity:1;"
offset="1"
id="stop2228"/>
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2224"
id="linearGradient2230"
x1="35.996582"
y1="40.458221"
x2="33.664921"
y2="37.770721"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(6.161836,4.033411)"/>
<linearGradient
inkscape:collect="always"
id="linearGradient2251">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop2253"/>
<stop
style="stop-color:#ffffff;stop-opacity:0;"
offset="1"
id="stop2255"/>
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2251"
id="linearGradient2257"
x1="33.396004"
y1="36.921333"
x2="34.170048"
y2="38.070381"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(6.161836,3.658411)"/>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15218"
id="linearGradient4258"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.065698,0.000000,0.000000,0.987595,-8.548320,-4.891713)"
x1="22.308331"
y1="18.992140"
x2="35.785294"
y2="39.498238"/>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2259"
id="linearGradient4260"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.998504,0.000000,0.000000,0.998246,-6.970391,-4.892901)"
x1="26.076092"
y1="26.696676"
x2="30.811172"
y2="42.007351"/>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2259"
id="linearGradient13651"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.999421,0.000000,0.000000,1.000000,5.991319,4.033411)"
x1="26.076092"
y1="26.696676"
x2="30.811172"
y2="42.007351"/>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient15218"
id="linearGradient13653"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.067236,0.000000,0.000000,0.989276,4.391684,4.035227)"
x1="22.308331"
y1="18.992140"
x2="35.785294"
y2="39.498238"/>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#bebebe"
borderopacity="1.0000000"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="-57.902952"
inkscape:cy="48.133585"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:grid-bbox="true"
inkscape:document-units="px"
inkscape:window-width="873"
inkscape:window-height="699"
inkscape:window-x="264"
inkscape:window-y="149"
inkscape:showpageshadow="false"/>
<metadata
id="metadata4203">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title>Edit Copy</dc:title>
<dc:date>2005-10-15</dc:date>
<dc:creator>
<cc:Agent>
<dc:title>Andreas Nilsson</dc:title>
</cc:Agent>
</dc:creator>
<dc:subject>
<rdf:Bag>
<rdf:li>edit</rdf:li>
<rdf:li>copy</rdf:li>
</rdf:Bag>
</dc:subject>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"/>
<dc:contributor>
<cc:Agent>
<dc:title>Jakub Steiner</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/">
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"/>
</cc:License>
</rdf:RDF>
</metadata>
<g
id="layer1"
inkscape:label="Layer 1"
inkscape:groupmode="layer">
<g
id="g4268"
style="opacity:0.49999997"
transform="matrix(1.001508,0.000000,0.000000,1.000616,-5.002205e-2,-6.304895e-2)">
<rect
y="34.033413"
x="20.161837"
height="2.0000000"
width="13.000000"
id="rect2279"
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
<rect
ry="0.56615961"
rx="0.56565511"
y="1.5629303"
x="1.5484408"
height="35.976688"
width="30.951559"
id="rect4238"
style="opacity:1.0000000;fill:url(#linearGradient4258);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#888a85;stroke-width:0.99893934;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"/>
<rect
ry="0.0000000"
rx="0.0000000"
y="2.5605955"
x="2.5325129"
height="33.981056"
width="28.970741"
id="rect4240"
style="opacity:1.0000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient4260);stroke-width:0.99893963;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"/>
<rect
y="10.033414"
x="7.0161190"
height="2.0000000"
width="21.000000"
id="rect4248"
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
<rect
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="rect4250"
width="20.000000"
height="2.0000000"
x="7.0161190"
y="14.033414"/>
<rect
y="18.033415"
x="7.0161190"
height="2.0000000"
width="18.000000"
id="rect4252"
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
<rect
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="rect4254"
width="21.000000"
height="2.0000000"
x="7.0161190"
y="22.033415"/>
<rect
y="26.033413"
x="7.0161190"
height="2.0000000"
width="13.000000"
id="rect4256"
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
</g>
<g
id="g12863">
<path
style="fill:url(#linearGradient13653);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#888a85;stroke-width:1.0000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
d="M 15.072946,10.500852 L 44.929331,10.500852 C 45.245071,10.500852 45.499257,10.753945 45.499257,11.068324 L 45.499257,38.235686 C 45.499257,40.712138 38.619447,46.538773 36.231325,46.538773 L 15.072946,46.538773 C 14.757206,46.538773 14.50302,46.285681 14.50302,45.9713 L 14.50302,11.068324 C 14.50302,10.753945 14.757206,10.500852 15.072946,10.500852 z "
id="rect12413"
sodipodi:nodetypes="ccccccccc"/>
<rect
ry="0.0000000"
rx="0.0000000"
y="11.500000"
x="15.502951"
height="34.040764"
width="28.997349"
id="rect15244"
style="opacity:1.0000000;fill:none;fill-opacity:1.0000000;fill-rule:evenodd;stroke:url(#linearGradient13651);stroke-width:1.0000008;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"/>
<path
sodipodi:nodetypes="cccc"
id="path2210"
d="M 36.220918,46.536966 C 38.251336,46.866864 45.809711,42.007037 45.505329,38.039122 C 43.942067,40.462219 40.746807,39.32586 36.638049,39.48487 C 36.638049,39.48487 37.033418,46.036966 36.220918,46.536966 z "
style="opacity:1.0000000;color:#000000;fill:url(#linearGradient2230);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#868a84;stroke-width:1.0000002;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
<path
style="opacity:0.36931817;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient2257);stroke-width:0.99999982;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
d="M 37.671355,44.345464 C 39.041134,43.661635 42.099604,42.198999 43.398985,40.317995 C 41.802891,40.99805 40.451175,40.527491 37.696651,40.5084 C 37.696651,40.5084 37.858973,43.570494 37.671355,44.345464 z "
id="path2247"
sodipodi:nodetypes="cccc"/>
<rect
y="19.033415"
x="20.000000"
height="2.0000000"
width="21.000000"
id="rect2271"
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
<rect
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="rect2273"
width="19.992233"
height="2.0000000"
x="20.000000"
y="23.033415"/>
<rect
y="27.033415"
x="20.000000"
height="2.0000000"
width="17.976702"
id="rect2275"
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"/>
<rect
style="opacity:0.17045452;color:#000000;fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;visibility:visible;display:inline;overflow:visible"
id="rect2277"
width="21.000000"
height="2.0000000"
x="20.000000"
y="31.033415"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -19,6 +19,7 @@
./expicon.sh View-zoom-out
./expicon.sh edit-redo
./expicon.sh edit-undo
./expicon.sh edit-copy
./expicon.sh measurement-graph
./expicon.sh dialog-error