001package jmri.jmrit.display; 002 003import java.awt.Point; 004import java.awt.Rectangle; 005import java.awt.event.MouseEvent; 006 007import javax.swing.JTextField; 008import javax.swing.SwingUtilities; 009 010/** 011 * A text field hosted by a positionable panel in an editor whose painting is 012 * zoomed with a Graphics transform. It keeps hit testing and mouse coordinates 013 * aligned with the scaled rendering. 014 */ 015class PositionableJTextField extends JTextField { 016 017 @Override 018 public void repaint(long tm, int x, int y, int width, int height) { 019 PositionableJPanel panel = getPositionablePanel(); 020 if (panel == null || panel.getParent() == null || panel.getEditor() == null 021 || panel.getEditor().getTargetPanel() == null) { 022 super.repaint(tm, x, y, width, height); 023 return; 024 } 025 026 Rectangle dirtyBounds = SwingUtilities.convertRectangle(this, 027 new Rectangle(x, y, width, height), panel.getEditor().getTargetPanel()); 028 panel.getEditor().repaintTargetPanel(dirtyBounds); 029 } 030 031 private PositionableJPanel getPositionablePanel() { 032 var parent = getParent(); 033 if (parent instanceof PositionableJPanel) { 034 return (PositionableJPanel) parent; 035 } else { 036 return null; 037 } 038 } 039 040 private Point getPanelOrigin() { 041 PositionableJPanel panel = getPositionablePanel(); 042 if (panel == null || panel.getEditor() == null || panel.getEditor().getTargetPanel() == null 043 || getParent() == null) { 044 return null; 045 } 046 return SwingUtilities.convertPoint(this, 0, 0, panel.getEditor().getTargetPanel()); 047 } 048 049 @Override 050 public boolean contains(int x, int y) { 051 PositionableJPanel panel = getPositionablePanel(); 052 Point origin = getPanelOrigin(); 053 if (panel == null || origin == null) { 054 return super.contains(x, y); 055 } 056 double scale = panel.getEditor().getPaintScale(); 057 if (scale == 1.0) { 058 return super.contains(x, y); 059 } 060 double unscaledX = (x + origin.x) / scale - origin.x; 061 double unscaledY = (y + origin.y) / scale - origin.y; 062 return unscaledX >= 0 && unscaledX < getWidth() 063 && unscaledY >= 0 && unscaledY < getHeight(); 064 } 065 066 @Override 067 protected void processMouseEvent(MouseEvent event) { 068 super.processMouseEvent(transformMouseEvent(event)); 069 } 070 071 @Override 072 protected void processMouseMotionEvent(MouseEvent event) { 073 super.processMouseMotionEvent(transformMouseEvent(event)); 074 } 075 076 private MouseEvent transformMouseEvent(MouseEvent event) { 077 PositionableJPanel panel = getPositionablePanel(); 078 Point origin = getPanelOrigin(); 079 if (panel == null || origin == null) { 080 return event; 081 } 082 double scale = panel.getEditor().getPaintScale(); 083 if (scale == 1.0) { 084 return event; 085 } 086 087 int x = (int) Math.round((event.getX() + origin.x) / scale - origin.x); 088 int y = (int) Math.round((event.getY() + origin.y) / scale - origin.y); 089 return new MouseEvent(this, event.getID(), event.getWhen(), event.getModifiersEx(), x, y, 090 event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), 091 event.isPopupTrigger(), event.getButton()); 092 } 093}