=== modified file 'src/com/goldencode/p2j/ui/client/WidgetRegistry.java' --- src/com/goldencode/p2j/ui/client/WidgetRegistry.java 2016-02-17 19:32:15 +0000 +++ src/com/goldencode/p2j/ui/client/WidgetRegistry.java 2016-03-08 19:39:00 +0000 @@ -49,12 +49,14 @@ ** 025 CA 20151123 Replaced root frame check with dedicated API. ** SBI 20151201 Added findAncestor/findDescendant for a given widget and a target widget type. ** 026 IAS 20160211 Thread-safe access to the widgetList. +** 027 SBI 20160307 Changed findAncestor method to accept a target filter predicate. */ package com.goldencode.p2j.ui.client; import java.util.*; import java.util.concurrent.locks.*; +import java.util.function.Predicate; import java.util.logging.*; import com.goldencode.p2j.ui.*; @@ -84,22 +86,22 @@ private final ReadWriteLock lock = new ReentrantReadWriteLock(); /** - * Returns a nearest widget's ancestor having a given type. + * Returns a nearest widget's ancestor that satisfies the target filter condition. * * @param w * The target widget that can have an ancestor of a given type. - * @param type - * The specified type condition. + * @param filter + * The target filter condition. * - * @return The ancestor having the specified type or null if there are no widgets - * satisfied this condition. + * @return The ancestor satisfied the target filter condition or null if there are no + * widgets satisfied this condition. */ - public static Widget findAncestor(Widget w, Class type) + public static Widget findAncestor(Widget w, Predicate filter) { Widget c = w; while (c != null) { - if (c.getClass().equals(type)) + if (filter.test(c)) { return c; } === modified file 'src/com/goldencode/p2j/ui/client/gui/EditorGuiImpl.java' --- src/com/goldencode/p2j/ui/client/gui/EditorGuiImpl.java 2016-03-08 18:14:25 +0000 +++ src/com/goldencode/p2j/ui/client/gui/EditorGuiImpl.java 2016-03-08 19:36:03 +0000 @@ -1386,11 +1386,14 @@ { Widget src = super.findMouseSource(p); - return (src == editor || src == contentPane || src == editorScroll - /* TODO: this will be removed: this == src.parent(EditorGuiImpl.class) */ ) ? - this : src; + // Exclude the mouse source component if it is unregistered ~ it have no id. (editor) + if (src == null || src.getId() == null) + { + return null; + } + + return (src == contentPane) ? this : src; } - /** * Get the widget's actual bounds === modified file 'src/com/goldencode/p2j/ui/client/gui/FrameGuiImpl.java' --- src/com/goldencode/p2j/ui/client/gui/FrameGuiImpl.java 2016-02-24 17:44:15 +0000 +++ src/com/goldencode/p2j/ui/client/gui/FrameGuiImpl.java 2016-03-08 19:39:00 +0000 @@ -61,6 +61,7 @@ ** 030 HC 20160203 Improved runtime support of FRAME:VIRTUAL* and FRAME:SCROLLABLE attributes. ** Frame layout improvements. ** 031 IAS 20160217 LOAD-MOUSE-POINTER support. +** 032 SBI 20160307 Changed an effective widget id for the frame's hover action. */ package com.goldencode.p2j.ui.client.gui; @@ -742,7 +743,8 @@ @Override protected MouseHoverAction createMouseHoverAction() { - return new MouseHoverAction(this) + // frame scroll component is the smallest widget that catch the mouse input and has an id. + return new MouseHoverAction(this, this.frameScroll.getId().asInt()) { @Override protected MousePtrWrapper parentCursor() === modified file 'src/com/goldencode/p2j/ui/client/gui/driver/swing/SwingMouseHandler.java' --- src/com/goldencode/p2j/ui/client/gui/driver/swing/SwingMouseHandler.java 2016-02-18 11:36:28 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/swing/SwingMouseHandler.java 2016-03-08 19:39:00 +0000 @@ -2,7 +2,7 @@ ** Module : WebMouseHandler.java ** Abstract : Provides mouse event support for the swing GUI driver. ** -** Copyright (c) 2015, Golden Code Development Corporation. +** Copyright (c) 2015-2016, Golden Code Development Corporation. ** ALL RIGHTS RESERVED. Use is subject to license terms. ** ** Golden Code Development Corporation @@ -18,6 +18,8 @@ ** window. ** 003 HC 20151013 NPE fix. ** 004 HC 20151024 Fixed race condition when dispatching mouse events. +** 005 SBI 20160307 Changed processAction to deliver mouse events to the closest registered widget +** in the source mouse widget parent's hierarchy. */ package com.goldencode.p2j.ui.client.gui.driver.swing; @@ -29,11 +31,14 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import com.goldencode.p2j.security.*; import com.goldencode.p2j.ui.WidgetId; import com.goldencode.p2j.ui.client.*; import com.goldencode.p2j.ui.client.event.*; +import com.goldencode.p2j.ui.client.gui.ScrollBarGuiImpl; +import com.goldencode.p2j.ui.client.gui.ScrollPaneGuiImpl; import com.goldencode.p2j.ui.client.gui.driver.*; import com.goldencode.p2j.ui.client.widget.*; @@ -161,7 +166,7 @@ { Widget mouseSource = findMouseSource(e); lastHoveredWidget = mouseSource; - + if (!processAction(e)) { SwingMouseHandler.super.mouseEntered(e); @@ -375,6 +380,7 @@ } Widget mouseSource = window.findMouseSource(new MouseEvt(e, window)); + return mouseSource; } @@ -415,7 +421,33 @@ return false; } - WidgetId wid = UiUtils.getWidgetId(widget); + // find widget in its ancestor's hierarchy that has an id + Widget parent = WidgetRegistry.findAncestor(widget, new Predicate() + { + @Override + public boolean test(Widget t) + { + return UiUtils.getWidgetId(t) != null; + } + }); + + // TODO: move this widget-specific logic into methods that are implemented in the widget + // hierarchy so that we do not have direct references to widget classes in this common code + + // if it is scroll bar then find its scroll pane parent + if (parent instanceof ScrollBarGuiImpl) + { + parent = WidgetRegistry.findAncestor(parent, new Predicate() + { + @Override + public boolean test(Widget t) + { + return ScrollPaneGuiImpl.class.equals(t.getClass()); + } + }); + } + + WidgetId wid = UiUtils.getWidgetId(parent); if (wid == null) { === modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/WebMouseHandler.java' --- src/com/goldencode/p2j/ui/client/gui/driver/web/WebMouseHandler.java 2016-02-29 18:42:34 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/WebMouseHandler.java 2016-03-08 19:39:00 +0000 @@ -19,6 +19,7 @@ package com.goldencode.p2j.ui.client.gui.driver.web; import java.awt.event.MouseEvent; +import java.util.function.Predicate; import com.goldencode.p2j.ui.client.*; import com.goldencode.p2j.ui.client.gui.*; @@ -62,7 +63,18 @@ } else { - Widget editor = WidgetRegistry.findAncestor(w, EditorGuiImpl.class); + // TODO: move this widget-specific logic into methods that are implemented in + // the widget hierarchy so that we do not have direct references to widget classes + // in this common code + + Widget editor = WidgetRegistry.findAncestor(target, new Predicate() + { + @Override + public boolean test(Widget t) + { + return EditorGuiImpl.class.equals(t.getClass()); + } + }); if (editor != null && editor.getId() != null) { widgetId = editor.getId().asInt(); === modified file 'src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.mouse.js' --- src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.mouse.js 2016-02-29 15:15:12 +0000 +++ src/com/goldencode/p2j/ui/client/gui/driver/web/res/p2j.mouse.js 2016-03-08 20:01:20 +0000 @@ -920,7 +920,21 @@ { removeListeners(win, mops, listeners); }; - + + this.getEvents = function() + { + var events = {}; + for (var prop in mops) + { + if (mops.hasOwnProperty(prop)) + { + events[prop] = true; + } + } + + return events; + }; + function processMouseDragStop(mThis, mouseOp) { return function(evt) === modified file 'src/com/goldencode/p2j/ui/client/widget/AbstractContainer.java' --- src/com/goldencode/p2j/ui/client/widget/AbstractContainer.java 2016-03-07 12:46:23 +0000 +++ src/com/goldencode/p2j/ui/client/widget/AbstractContainer.java 2016-03-08 19:30:14 +0000 @@ -372,8 +372,7 @@ continue; } - return (found != null && found.getId() != null) ? found : - (w.getId() == null ? null : w); + return (found == null) ? w : found; } return null;