1 | classdef MousePointerHandler < handle |
---|
2 | %MousePointerHandler A class to handle mouse-over events |
---|
3 | % |
---|
4 | % MousePointerHandler(fig) attaches the handler to the figure FIG |
---|
5 | % so that it will intercept all mouse-over events. The handler is |
---|
6 | % stored in the MousePointerHandler app-data of the figure so that |
---|
7 | % functions can listen in for scroll-events. |
---|
8 | % |
---|
9 | % Examples: |
---|
10 | % >> f = figure(); |
---|
11 | % >> u = uicontrol(); |
---|
12 | % >> mph = uiextras.MousePointerHandler(f); |
---|
13 | % >> mph.register( u, 'fleur' ) |
---|
14 | % |
---|
15 | % See also: uiextras.ScrollWheelEvent |
---|
16 | |
---|
17 | % Copyright 2008-2010 The MathWorks Ltd. |
---|
18 | % 1.1 |
---|
19 | % 2012/05/08 08:02:58 |
---|
20 | |
---|
21 | properties( SetAccess = private, GetAccess = public ) |
---|
22 | CurrentObject |
---|
23 | end % read-only public properties |
---|
24 | |
---|
25 | properties( SetAccess = private , GetAccess = private ) |
---|
26 | CurrentObjectPosition |
---|
27 | OldPointer |
---|
28 | Parent |
---|
29 | List |
---|
30 | end % private properties |
---|
31 | |
---|
32 | methods |
---|
33 | |
---|
34 | function obj = MousePointerHandler(fig) |
---|
35 | % Check that a mouse-pointer-handler is not already there |
---|
36 | if ~isa( fig, 'figure' ) |
---|
37 | fig = ancestor( fig, 'figure' ); |
---|
38 | end |
---|
39 | if isappdata(fig,'MousePointerHandler') |
---|
40 | obj = getappdata(fig,'MousePointerHandler'); |
---|
41 | else |
---|
42 | set(fig,'WindowButtonMotionFcn', @obj.onMouseMoved); |
---|
43 | setappdata(fig,'MousePointerHandler',obj); |
---|
44 | obj.Parent = fig; |
---|
45 | end |
---|
46 | end % MousePointerHandler |
---|
47 | |
---|
48 | function register( obj, widget, pointer ) |
---|
49 | % We need to be sure to remove the entry if it dies |
---|
50 | if isHGUsingMATLABClasses() |
---|
51 | % New style |
---|
52 | l = event.listener( widget, 'ObjectBeingDestroyed', @obj.onWidgetBeingDestroyedEvent ); |
---|
53 | else |
---|
54 | % Old school |
---|
55 | l = handle.listener( widget, 'ObjectBeingDestroyed', @obj.onWidgetBeingDestroyedEvent ); |
---|
56 | end |
---|
57 | entry = struct( ... |
---|
58 | 'Widget', widget, ... |
---|
59 | 'Pointer', pointer, ... |
---|
60 | 'Listener', l ); |
---|
61 | if isempty(obj.List) |
---|
62 | obj.List = entry; |
---|
63 | else |
---|
64 | obj.List(end+1,1) = entry; |
---|
65 | end |
---|
66 | end % register |
---|
67 | |
---|
68 | end % public methods |
---|
69 | |
---|
70 | methods( Access = private ) |
---|
71 | |
---|
72 | function onMouseMoved( obj, src, evt ) %#ok<INUSD> |
---|
73 | if isempty( obj.List ) |
---|
74 | return; |
---|
75 | end |
---|
76 | figh = obj.Parent; |
---|
77 | figUnits = get( figh, 'Units' ); |
---|
78 | currpos = get( figh, 'CurrentPoint' ); |
---|
79 | if ~strcmpi( figUnits, 'Pixels' ) |
---|
80 | currpos = hgconvertunits( figh, [currpos,0,0], figUnits, 'pixels', 0 ); |
---|
81 | end |
---|
82 | if ~isempty( obj.CurrentObjectPosition ) |
---|
83 | cop = obj.CurrentObjectPosition; |
---|
84 | if currpos(1) >= cop(1) ... |
---|
85 | && currpos(1) < cop(1)+cop(3) ... |
---|
86 | && currpos(2) >= cop(2) ... |
---|
87 | && currpos(2) < cop(2)+cop(4) |
---|
88 | % Still inside, so do nothing |
---|
89 | return; |
---|
90 | else |
---|
91 | % Left the object |
---|
92 | obj.leaveWidget() |
---|
93 | end |
---|
94 | end |
---|
95 | % OK, now scan the objects to see if we're inside |
---|
96 | for ii=1:numel(obj.List) |
---|
97 | % We need to be careful of widgets that aren't capable of |
---|
98 | % returning a PixelPosition |
---|
99 | try |
---|
100 | widgetpos = getpixelposition( obj.List(ii).Widget, true ); |
---|
101 | if currpos(1) >= widgetpos(1) ... |
---|
102 | && currpos(1) < widgetpos(1)+widgetpos(3) ... |
---|
103 | && currpos(2) >= widgetpos(2) ... |
---|
104 | && currpos(2) < widgetpos(2)+widgetpos(4) |
---|
105 | % Inside |
---|
106 | obj.enterWidget( obj.List(ii).Widget, widgetpos, obj.List(ii).Pointer ) |
---|
107 | break; % we don't need to carry on looking |
---|
108 | end |
---|
109 | catch err %#ok<NASGU> |
---|
110 | warning( 'MousePointerHandler:BadWidget', 'GETPIXELPOSITION failed for widget %d', ii ) |
---|
111 | end |
---|
112 | end |
---|
113 | |
---|
114 | end % onMouseMoved |
---|
115 | |
---|
116 | function onWidgetBeingDestroyedEvent( obj, src,evt ) %#ok<INUSD> |
---|
117 | idx = cellfun( @isequal, {obj.List.Widget}, repmat( {double(src)}, 1,numel(obj.List) ) ); |
---|
118 | obj.List(idx) = []; |
---|
119 | % Also take care if it's the active object |
---|
120 | if isequal( src, obj.CurrentObject ) |
---|
121 | obj.leaveWidget() |
---|
122 | end |
---|
123 | end % onWidgetBeingDestroyedEvent |
---|
124 | |
---|
125 | function enterWidget( obj, widget, pixpos, pointer ) |
---|
126 | % Mouse has moved onto a widget |
---|
127 | obj.CurrentObjectPosition = pixpos; |
---|
128 | obj.CurrentObject = widget; |
---|
129 | obj.OldPointer = get( obj.Parent, 'Pointer' ); |
---|
130 | set( obj.Parent, 'Pointer', pointer ); |
---|
131 | %fprintf( 'Enter widget ''%s''\n', get( widget, 'Tag' ) ); |
---|
132 | end % enterWidget |
---|
133 | |
---|
134 | function leaveWidget( obj ) |
---|
135 | % Mouse has moved off a widget |
---|
136 | %if ~isempty( obj.CurrentObject ) |
---|
137 | % fprintf( 'Leave widget ''%s''\n', get( obj.CurrentObject, 'Tag' ) ); |
---|
138 | %end |
---|
139 | obj.CurrentObjectPosition = []; |
---|
140 | obj.CurrentObject = []; |
---|
141 | set( obj.Parent, 'Pointer', obj.OldPointer ); |
---|
142 | end % leaveWidget |
---|
143 | |
---|
144 | end % private methods |
---|
145 | |
---|
146 | end % classdef |
---|