@@ -161,6 +161,7 @@ public LayoutEditorToolBarPanel getLayoutEditorToolBarPanel() {
161161 private JCheckBoxMenuItem turnoutFillControlCirclesCheckBoxMenuItem = null ;
162162 private JCheckBoxMenuItem hideTrackSegmentConstructionLinesCheckBoxMenuItem = null ;
163163 private JCheckBoxMenuItem useDirectTurnoutControlCheckBoxMenuItem = null ;
164+ private JCheckBoxMenuItem highlightCursorCheckBoxMenuItem = null ;
164165 private ButtonGroup turnoutCircleSizeButtonGroup = null ;
165166
166167 private boolean turnoutDrawUnselectedLeg = true ;
@@ -308,6 +309,7 @@ public LayoutEditorFindItems getFinder() {
308309 private double xOverHWid = LayoutTurnout .xOverHWidDefault ;
309310 private double xOverShort = LayoutTurnout .xOverShortDefault ;
310311 private boolean useDirectTurnoutControl = false ; // Uses Left click for closing points, Right click for throwing.
312+ private boolean highlightCursor = false ; // Highlight finger/mouse press/drag area, good for touchscreens
311313
312314 // saved state of options when panel was loaded or created
313315 private boolean savedEditMode = true ;
@@ -1104,6 +1106,15 @@ private JMenu setupOptionMenu(@Nonnull JMenuBar menuBar) {
11041106 });
11051107 drawLayoutTracksLabelCheckBoxMenuItem .setSelected (drawLayoutTracksLabel );
11061108
1109+ // add "Highlight cursor position" - useful for touchscreens
1110+ highlightCursorCheckBoxMenuItem = new JCheckBoxMenuItem (Bundle .getMessage ("HighlightCursor" ));
1111+ optionMenu .add (highlightCursorCheckBoxMenuItem );
1112+ highlightCursorCheckBoxMenuItem .addActionListener ((ActionEvent event ) -> {
1113+ highlightCursor = highlightCursorCheckBoxMenuItem .isSelected ();
1114+ redrawPanel ();
1115+ });
1116+ highlightCursorCheckBoxMenuItem .setSelected (highlightCursor );
1117+
11071118 //
11081119 // edit title
11091120 //
@@ -1958,11 +1969,8 @@ private void setupZoomMenu(@Nonnull JMenuBar menuBar) {
19581969 // get the window specific saved zoom user preference
19591970 InstanceManager .getOptionalDefault (UserPreferencesManager .class ).ifPresent ((prefsMgr ) -> {
19601971 Object zoomProp = prefsMgr .getProperty (getWindowFrameRef (), "zoom" );
1961-
19621972 log .debug ("{} zoom is {}" , getWindowFrameRef (), zoomProp );
1963-
1964- if (zoomProp
1965- != null ) {
1973+ if (zoomProp != null ) {
19661974 setZoom ((Double ) zoomProp );
19671975 }
19681976 }
@@ -2172,7 +2180,6 @@ public void mouseWheelMoved(@Nonnull MouseWheelEvent event) {
21722180 * @param zoomFactor eg. 0.5 ( 1/2 zoom ), 1.0 ( no zoom ), 2.0 ( 2x zoom )
21732181 */
21742182 private void selectZoomMenuItem (double zoomFactor ) {
2175-
21762183 double zoom = zoomFactor * 100 ;
21772184
21782185 // put zoomFactor on 100% increments
@@ -2957,6 +2964,29 @@ private Point2D calcLocation(JmriMouseEvent event) {
29572964 return calcLocation (event , 0 , 0 );
29582965 }
29592966
2967+ /**
2968+ * Check for highlighting of cursor position.
2969+ *
2970+ * If in "highlight" mode, draw a square at the location of the
2971+ * event. If there was already a square, just move its location.
2972+ * In either case, redraw the panel so the previous square will
2973+ * disappear and the new one will appear immediately.
2974+ */
2975+ private void checkHighlightCursor () {
2976+ if (!isEditable () && highlightCursor ) {
2977+ // rectangle size based on turnout circle size: rectangle should
2978+ // be bigger so it can more easily surround turnout on screen
2979+ int halfSize = (int )(circleRadius ) + 8 ;
2980+ if (_highlightcomponent == null ) {
2981+ _highlightcomponent = new Rectangle (
2982+ xLoc - halfSize , yLoc - halfSize , halfSize * 2 , halfSize * 2 );
2983+ } else {
2984+ _highlightcomponent .setLocation (xLoc - halfSize , yLoc - halfSize );
2985+ }
2986+ redrawPanel ();
2987+ }
2988+ }
2989+
29602990 /**
29612991 * Handle a mouse pressed event
29622992 * <p>
@@ -2974,6 +3004,8 @@ public void mousePressed(JmriMouseEvent event) {
29743004 _lastY = _anchorY ;
29753005 calcLocation (event );
29763006
3007+ checkHighlightCursor ();
3008+
29773009 // TODO: Add command-click on nothing to pan view?
29783010 if (isEditable ()) {
29793011 boolean prevSelectionActive = selectionActive ;
@@ -3505,6 +3537,13 @@ public void mouseReleased(JmriMouseEvent event) {
35053537 // initialize mouse position
35063538 calcLocation (event );
35073539
3540+ if (!isEditable () && _highlightcomponent != null && highlightCursor ) {
3541+ _highlightcomponent = null ;
3542+ // see if we moused up on an object
3543+ checkControls (true );
3544+ redrawPanel ();
3545+ }
3546+
35083547 // if alt modifier is down invert the snap to grid behaviour
35093548 snapToGridInvert = event .isAltDown ();
35103549
@@ -3654,6 +3693,19 @@ && allControlling() && !event.isMetaDown() && !event.isAltDown() && !event.isPop
36543693 t .setState (Turnout .CLOSED );
36553694 } else {
36563695 t .toggleTurnout ();
3696+ if (highlightCursor && !t .isDisabled ()) {
3697+ // flash the turnout circle a few times so the user knows it's being toggled
3698+ javax .swing .Timer timer = new javax .swing .Timer (150 , null );
3699+ timer .addActionListener (new ActionListener (){
3700+ int count = 1 ;
3701+ public void actionPerformed (ActionEvent ae ){
3702+ if (count % 2 != 0 ) t .setDisabled (true );
3703+ else t .setDisabled (false );
3704+ if (++count > 8 ) timer .stop ();
3705+ }
3706+ });
3707+ timer .start ();
3708+ }
36573709 }
36583710 } else if ((selectedObject != null ) && ((selectedHitPointType == HitPointType .SLIP_LEFT )
36593711 || (selectedHitPointType == HitPointType .SLIP_RIGHT ))
@@ -3997,6 +4049,11 @@ public void mouseClicked(@Nonnull JmriMouseEvent event) {
39974049 // initialize mouse position
39984050 calcLocation (event );
39994051
4052+ if (!isEditable () && _highlightcomponent != null && highlightCursor ) {
4053+ _highlightcomponent = null ;
4054+ redrawPanel ();
4055+ }
4056+
40004057 // if alt modifier is down invert the snap to grid behaviour
40014058 snapToGridInvert = event .isAltDown ();
40024059
@@ -4837,6 +4894,8 @@ public void mouseDragged(@Nonnull JmriMouseEvent event) {
48374894 // initialize mouse position
48384895 calcLocation (event );
48394896
4897+ checkHighlightCursor ();
4898+
48404899 // ignore this event if still at the original point
48414900 if ((!isDragging ) && (xLoc == getAnchorX ()) && (yLoc == getAnchorY ())) {
48424901 return ;
@@ -7477,6 +7536,10 @@ public boolean isTurnoutDrawUnselectedLeg() {
74777536 return turnoutDrawUnselectedLeg ;
74787537 }
74797538
7539+ public boolean isHighlightCursor () {
7540+ return highlightCursor ;
7541+ }
7542+
74807543 public String getLayoutName () {
74817544 return layoutName ;
74827545 }
@@ -7690,6 +7753,19 @@ public void setTurnoutDrawUnselectedLeg(boolean state) {
76907753 }
76917754 }
76927755
7756+ /**
7757+ * Should only be invoked on the GUI (Swing) thread.
7758+ *
7759+ * @param state true to enable highlighting the cursor (mouse/finger press/drag)
7760+ */
7761+ @ InvokeOnGuiThread
7762+ public void setHighlightCursor (boolean state ) {
7763+ if (highlightCursor != state ) {
7764+ highlightCursor = state ;
7765+ highlightCursorCheckBoxMenuItem .setSelected (highlightCursor );
7766+ }
7767+ }
7768+
76937769 /**
76947770 * @param color value to set the default text color to.
76957771 */
0 commit comments