Ignore:
Timestamp:
09/02/14 17:34:42 (10 years ago)
Author:
jts21
Message:

Avoided JfxBrowser build error (caused by having to use internal APIs which can change), by using reflection to get the methods at runtime if they are present

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/items/widgets/JfxBrowser.java

    r919 r921  
    3333import java.io.InputStreamReader;
    3434import java.lang.reflect.Field;
     35import java.lang.reflect.Method;
    3536
    3637import javafx.animation.FadeTransition;
     
    508509                                @Override
    509510                                public void handle(MouseEvent e) {
    510                                         TextFieldSkin skin = (TextFieldSkin) JfxBrowser.this._urlField.getSkin();
    511                                        
    512511                                        if (!JfxBrowser.this._urlField.isDisabled()) {
    513512                        if (JfxBrowser.this._buttonDownId == MouseButton.MIDDLE || JfxBrowser.this._buttonDownId == MouseButton.SECONDARY) {
    514513                            if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
    515                                 skin.positionCaret(skin.getIndex(e), true);
     514                                setCaretFromCoord(JfxBrowser.this._urlField, e);
    516515                            }
    517516                        }
     
    10401039        }
    10411040       
     1041        /**
     1042         * Get internal JavaFX methods via reflection at runtime.<br>
     1043         * These are internal API methods for converting mouse (pixel) position to caret (text) position.
     1044         * This is used because JavaFX does not appear to support this functionality in any public API.
     1045         * This class solves two problems:
     1046         *  - If the system we are compiling on does not have the method, it should still compile
     1047         *  - If the system we are running on does not have the method, it should still run
     1048         *    (just without the expeditee-like URL bar text selection)
     1049         * Unfortunately it will still fail if the internal API ever removes the TextFieldSkin or HitInfo classes,
     1050         * But that is unavoidable without a compile-time preprocessor or some greater hacks
     1051         */
     1052        private static final class kludges {
     1053               
     1054                private static Method getGetIndex() {
     1055                        try {
     1056                                return TextFieldSkin.class.getMethod("getIndex", MouseEvent.class);
     1057                        } catch(Exception e) {
     1058                                return null;
     1059                        }
     1060                }
     1061                private static Method getGetInsertionIndex() {
     1062                        try {
     1063                                return HitInfo.class.getMethod("getInsertionIndex");
     1064                        } catch(Exception e) {
     1065                                return null;
     1066                        }
     1067                }
     1068                private static Method getPositionCaret() {
     1069                        try {
     1070                                return TextFieldSkin.class.getMethod("positionCaret", HitInfo.class,  boolean.class);
     1071                        } catch(Exception e) {
     1072                                return null;
     1073                        }
     1074                }
     1075               
     1076                private static final Method getIndex = getGetIndex();
     1077                private static final Method getInsertionIndex = getGetInsertionIndex();
     1078                private static final Method positionCaret = getPositionCaret();
     1079                private static final boolean enabled = (getIndex != null && getInsertionIndex != null && positionCaret != null);
     1080        }
     1081       
     1082        /**
     1083         * Attempts to get the caret (text) position for a given pixel (MouseEvent) position
     1084         *
     1085         * @param text The textfield to find the caret position for
     1086         * @param e The MouseEvent containing the coordinates to convert to caret position
     1087         *
     1088         * @return The caret position if successful, otherwise the current caret position of the TextField.
     1089         */
    10421090        private int getCaretFromCoord(TextField text, MouseEvent e) {
    1043                 TextFieldSkin skin = (TextFieldSkin) text.getSkin();
    1044                 HitInfo hit = skin.getIndex(e);
    1045                 return hit.getInsertionIndex();
     1091                if (kludges.enabled) {
     1092                        try {
     1093                                return (int) kludges.getInsertionIndex.invoke(kludges.getIndex.invoke(text.getSkin(), e));
     1094                        } catch (Exception ex) {
     1095                                ex.printStackTrace();
     1096                        }
     1097                }
     1098                return text.getCaretPosition();
     1099        }
     1100       
     1101        /**
     1102         * Attempts to set the caret (text) position from a given pixel (MouseEvent) position
     1103         *
     1104         * @param text The textfield to set the caret position of
     1105         * @param e The MouseEvent containing the coordinates to convert to caret position
     1106         */
     1107        private void setCaretFromCoord(TextField text, MouseEvent e) {
     1108                if (kludges.enabled) {
     1109                        try {
     1110                                Object skin = text.getSkin();
     1111                                kludges.positionCaret.invoke(skin, kludges.getIndex.invoke(skin, e), true);
     1112                        } catch (Exception ex) {
     1113                                ex.printStackTrace();
     1114                        }
     1115                }
    10461116        }
    10471117       
Note: See TracChangeset for help on using the changeset viewer.