2017-09-28 08:59:57 -07:00
/ *
2017-10-15 15:36:42 -07:00
Copyright ( c ) 2017 , Lars Brubaker , John Lewin
2017-09-28 08:59:57 -07:00
All rights reserved .
Redistribution and use in source and binary forms , with or without
modification , are permitted provided that the following conditions are met :
1. Redistributions of source code must retain the above copyright notice , this
list of conditions and the following disclaimer .
2. Redistributions in binary form must reproduce the above copyright notice ,
this list of conditions and the following disclaimer in the documentation
and / or other materials provided with the distribution .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies ,
either expressed or implied , of the FreeBSD Project .
* /
using System ;
using MatterHackers.Agg ;
using MatterHackers.Agg.UI ;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class PopupButton : GuiWidget , IIgnoredPopupChild
{
2018-04-09 13:15:17 -07:00
public Color HoverColor { get ; set ; } = new Color ( 0 , 0 , 0 , 40 ) ;
2017-09-28 08:59:57 -07:00
2017-11-07 11:31:30 -08:00
public event EventHandler PopupWindowClosed ;
2017-12-19 17:06:33 -08:00
public event EventHandler BeforePopup ;
2018-01-02 13:45:15 -08:00
2018-04-09 13:15:17 -07:00
protected GuiWidget buttonView ;
2017-09-28 08:59:57 -07:00
private bool menuVisibileAtMouseDown = false ;
private bool menuVisible = false ;
private PopupWidget popupWidget ;
public PopupButton ( )
{
}
public PopupButton ( GuiWidget buttonView )
{
this . HAnchor = HAnchor . Fit ;
2018-01-21 21:07:14 -08:00
this . VAnchor = VAnchor . Fit | VAnchor . Center ;
2017-09-28 08:59:57 -07:00
this . buttonView = buttonView ;
this . buttonView . Selectable = false ;
this . AddChild ( buttonView ) ;
}
public bool AlignToRightEdge { get ; set ; }
2018-01-21 21:07:14 -08:00
public virtual Func < GuiWidget > DynamicPopupContent { get ; set ; }
2017-09-28 08:59:57 -07:00
public IPopupLayoutEngine PopupLayoutEngine { get ; set ; }
public Direction PopDirection { get ; set ; } = Direction . Down ;
public bool MakeScrollable { get ; set ; } = true ;
2018-01-21 21:07:14 -08:00
public virtual GuiWidget PopupContent { get ; set ; }
2017-09-28 08:59:57 -07:00
2018-06-23 14:17:39 -07:00
public Color PopupBorderColor { get ; set ; } = Color . Transparent ;
2018-04-09 13:15:17 -07:00
2017-09-28 08:59:57 -07:00
public override void OnMouseDown ( MouseEventArgs mouseEvent )
{
// Store the menu state at the time of mousedown
menuVisibileAtMouseDown = menuVisible ;
base . OnMouseDown ( mouseEvent ) ;
}
public override void OnMouseUp ( MouseEventArgs mouseEvent )
{
// HACK: Child controls seem to be interfering with this.MouseCaptured - this short term workaround ensure we get clicks but likely mean mouse down outside of the control will fire the popup
bool mouseUpInBounds = this . PositionWithinLocalBounds ( mouseEvent . X , mouseEvent . Y ) ;
// Only show the popup if the menu was hidden as the mouse events started
if ( ( mouseUpInBounds | | buttonView ? . MouseCaptured = = true )
& & ! menuVisibileAtMouseDown )
{
2018-03-14 13:23:19 -07:00
UiThread . RunOnIdle ( this . ShowPopup ) ;
2017-09-28 08:59:57 -07:00
}
base . OnMouseUp ( mouseEvent ) ;
}
2018-01-02 13:45:15 -08:00
public override void OnDraw ( Graphics2D graphics2D )
2018-01-01 11:30:51 -08:00
{
if ( menuVisible )
{
2018-04-09 13:15:17 -07:00
graphics2D . FillRectangle ( this . LocalBounds , HoverColor ) ;
2018-01-01 11:30:51 -08:00
}
2018-01-02 13:45:15 -08:00
base . OnDraw ( graphics2D ) ;
2018-01-01 11:30:51 -08:00
}
2017-09-28 08:59:57 -07:00
public void ShowPopup ( )
{
if ( PopupLayoutEngine = = null )
{
PopupLayoutEngine = new PopupLayoutEngine ( this . PopupContent , this , this . PopDirection , 0 , this . AlignToRightEdge ) ;
}
menuVisible = true ;
this . PopupContent ? . ClearRemovedFlag ( ) ;
if ( this . DynamicPopupContent ! = null )
{
this . PopupContent = this . DynamicPopupContent ( ) ;
}
2018-03-14 13:27:21 -07:00
if ( this . PopupContent = = null
| | this . PopupContent . Children . Count < = 0 )
2017-09-28 08:59:57 -07:00
{
2018-03-14 13:27:21 -07:00
menuVisible = false ;
2017-09-28 08:59:57 -07:00
return ;
}
2017-12-19 17:06:33 -08:00
this . OnBeforePopup ( ) ;
2017-09-28 08:59:57 -07:00
popupWidget = new PopupWidget ( this . PopupContent , PopupLayoutEngine , MakeScrollable )
{
BorderWidth = 1 ,
2018-04-09 13:15:17 -07:00
BorderColor = this . PopupBorderColor ,
2017-09-28 08:59:57 -07:00
} ;
popupWidget . Closed + = ( s , e ) = >
{
menuVisible = false ;
popupWidget = null ;
2017-11-07 11:31:30 -08:00
this . PopupWindowClosed ? . Invoke ( this , null ) ;
2017-09-28 08:59:57 -07:00
} ;
2018-03-14 13:23:19 -07:00
2017-09-28 08:59:57 -07:00
popupWidget . Focus ( ) ;
}
2017-12-19 17:06:33 -08:00
protected virtual void OnBeforePopup ( )
2017-09-28 08:59:57 -07:00
{
2017-12-19 17:06:33 -08:00
this . BeforePopup ? . Invoke ( this , null ) ;
2017-09-28 08:59:57 -07:00
}
2018-09-11 10:57:53 -07:00
public bool KeepMenuOpen ( )
{
2018-10-01 15:18:23 -07:00
return menuVisible ;
2018-09-11 10:57:53 -07:00
}
2017-09-28 08:59:57 -07:00
}
}