1 // Written in the D programming language. 2 /++ 3 + Authors: KanzakiKino 4 + Copyright: KanzakiKino 2018 5 + License: LGPL-3.0 6 ++/ 7 module w4d.widget.base.mouse; 8 9 /// A template that declares methods related to Mouse. 10 template Mouse () 11 { 12 protected Widget _hovered; 13 14 protected void setHovered ( Widget child, vec2 pos ) 15 { 16 auto temp = _hovered; 17 _hovered = child; 18 19 if ( child !is temp ) { 20 if ( temp ) temp .handleMouseEnter( false, pos ); 21 if ( child ) child.handleMouseEnter( true, pos ); 22 } 23 } 24 25 @property const(Cursor) cursor () 26 { 27 return _hovered? _hovered.cursor: Cursor.Arrow; 28 } 29 30 31 @property isTracked () 32 { 33 return _context && _context.tracked is this; 34 } 35 @property bool trackable () 36 { 37 return true; 38 } 39 void track () 40 { 41 if ( trackable ) { 42 enforce( _context, "WindowContext is null." ); 43 _context.setTracked( this ); 44 } 45 } 46 void refuseTrack () 47 { 48 enforce( isTracked, "The widget has not been tracked." ); 49 _context.setTracked( null ); 50 } 51 52 53 bool handleMouseEnter ( bool entered, vec2 pos ) 54 { 55 if ( _context.tracked && !isTracked ) { 56 return true; 57 } 58 59 if ( entered ) { 60 enableState( WidgetState.Hovered ); 61 } else { 62 setHovered( null, pos ); 63 disableState( WidgetState.Hovered ); 64 } 65 return false; 66 } 67 68 bool handleMouseMove ( vec2 pos ) 69 { 70 if ( !isTracked ) { 71 if ( _context.tracked ) { 72 _context.tracked.handleMouseMove( pos ); 73 return true; 74 } else if ( auto target = findChildAt(pos) ) { 75 setHovered( target, pos ); 76 if ( target.handleMouseMove( pos ) ) { 77 return true; 78 } 79 } else { 80 setHovered( null, pos ); 81 } 82 } 83 return false; 84 } 85 86 bool handleMouseButton ( MouseButton btn, bool status, vec2 pos ) 87 { 88 if ( !isTracked ) { 89 if ( _context.tracked ) { 90 _context.tracked.handleMouseButton( btn, status, pos ); 91 return true; 92 } else if ( auto target = findChildAt(pos) ) { 93 if ( target.handleMouseButton( btn, status, pos ) ) { 94 return true; 95 } 96 if ( _context.tracked ) { 97 return true; 98 } 99 } 100 } 101 102 if ( btn == MouseButton.Left && status ) { 103 enableState( WidgetState.Pressed ); 104 track(); 105 focus(); 106 } else if ( btn == MouseButton.Left && !status ) { 107 if ( isTracked ) refuseTrack(); 108 disableState( WidgetState.Pressed ); 109 } 110 return false; 111 } 112 113 bool handleMouseScroll ( vec2 amount, vec2 pos ) 114 { 115 if ( !isTracked ) { 116 if ( _context.tracked ) { 117 _context.tracked.handleMouseScroll( amount, pos ); 118 return true; 119 } else if ( auto target = findChildAt(pos) ) { 120 if ( target.handleMouseScroll( amount, pos ) ) { 121 return true; 122 } 123 } 124 } 125 return false; 126 } 127 128 void handleTracked ( bool a ) 129 { 130 (a? &enableState: &disableState)( WidgetState.Tracked ); 131 } 132 }