2017-12-26 09:10:42 -08:00
/ *
2022-07-16 07:46:44 -07:00
Copyright ( c ) 2022 , Lars Brubaker , John Lewin
2017-12-26 09:10:42 -08: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 .
* /
2018-01-01 11:32:59 -08:00
using System ;
2018-01-21 21:07:14 -08:00
using System.Collections.Generic ;
2018-01-21 20:45:45 -08:00
using System.IO ;
using System.Linq ;
2017-12-28 12:51:47 -08:00
using MatterHackers.Agg ;
2018-08-29 08:25:59 -07:00
using MatterHackers.Agg.Image ;
2018-01-21 20:45:45 -08:00
using MatterHackers.Agg.Platform ;
using MatterHackers.Agg.UI ;
2021-05-21 15:23:25 -07:00
using MatterHackers.ImageProcessing ;
2022-03-15 17:51:28 -07:00
using MatterHackers.MatterControl.Library.Widgets ;
2017-12-26 09:10:42 -08:00
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class OverflowBar : Toolbar
{
2020-07-18 13:48:38 -07:00
protected static HashSet < Type > ignoredTypes = new HashSet < Type > { typeof ( HorizontalLine ) , typeof ( TextEditWithInlineCancel ) } ;
protected static HashSet < Type > ignoredInMenuTypes = new HashSet < Type > { typeof ( VerticalLine ) , typeof ( HorizontalLine ) , typeof ( TextEditWithInlineCancel ) , typeof ( HorizontalSpacer ) } ;
2018-01-21 21:07:14 -08:00
2022-07-16 07:46:44 -07:00
public OverflowBar ( ThemeConfig theme , string text = null )
: this ( null , theme , text )
2018-08-29 08:25:59 -07:00
{ }
2022-06-19 15:02:05 -07:00
public OverflowBar ( ImageBuffer icon , ThemeConfig theme , string text = null )
2020-10-26 16:40:36 -07:00
: base ( theme . TabbarPadding )
2017-12-26 09:10:42 -08:00
{
2018-01-21 20:45:45 -08:00
this . theme = theme ;
2018-01-01 21:22:40 -08:00
2018-08-29 08:25:59 -07:00
if ( icon = = null )
2018-01-01 21:22:40 -08:00
{
2022-06-19 15:02:05 -07:00
if ( text ! = null )
2018-08-29 08:25:59 -07:00
{
2022-06-19 15:02:05 -07:00
this . OverflowButton = new PopupMenuButton ( text , theme )
{
AlignToRightEdge = true ,
DrawArrow = true ,
} ;
}
else
{
this . OverflowButton = new OverflowMenuButton ( this , theme )
{
AlignToRightEdge = true ,
} ;
}
2018-08-29 08:25:59 -07:00
}
else
{
this . OverflowButton = new OverflowMenuButton ( this , icon , theme )
{
AlignToRightEdge = true ,
} ;
}
2022-06-19 15:02:05 -07:00
AddMenuItemsFunction ( OverflowButton ) ;
2017-12-26 09:10:42 -08:00
2018-04-26 07:56:29 -07:00
// We want to set right margin to overflow button width but width is already scaled - need to inflate value by amount needed to hit width when rescaled in Margin setter
this . ActionArea . Margin = new BorderDouble ( right : Math . Ceiling ( this . OverflowButton . Width / GuiWidget . DeviceScale ) ) ;
2018-04-07 09:50:52 -07:00
this . SetRightAnchorItem ( this . OverflowButton ) ;
2017-12-26 09:10:42 -08:00
}
2018-01-21 20:45:45 -08:00
private ThemeConfig theme ;
2022-06-19 15:02:05 -07:00
public PopupMenuButton OverflowButton { get ; }
2018-01-21 20:45:45 -08:00
public Action < PopupMenu > ExtendOverflowMenu { get ; set ; }
protected virtual void OnExtendPopupMenu ( PopupMenu popupMenu )
{
this . ExtendOverflowMenu ( popupMenu ) ;
}
public override void OnBoundsChanged ( EventArgs e )
{
2018-04-26 07:56:29 -07:00
base . OnBoundsChanged ( e ) ;
2018-01-21 20:45:45 -08:00
if ( this . RightAnchorItem = = null )
{
return ;
}
double maxRight = this . Width - RightAnchorItem . Width ;
2018-04-26 07:56:29 -07:00
//double maxRight = this.Width - this.Padding.Width - RightAnchorItem.Width - RightAnchorItem.Margin.Width;
2018-01-21 20:45:45 -08:00
2018-02-08 22:37:58 -08:00
double accumulatedX = 0 ;
bool withinLimits = true ;
2018-01-22 12:11:36 -08:00
2018-01-21 21:07:14 -08:00
foreach ( var widget in this . ActionArea . Children . Where ( c = > ! ignoredTypes . Contains ( c . GetType ( ) ) ) )
2018-01-21 20:45:45 -08:00
{
2020-09-12 11:06:13 -07:00
var totalX = widget . Width + widget . DeviceMarginAndBorder . Width ;
2018-01-22 12:11:36 -08:00
2018-07-16 14:03:19 -07:00
withinLimits & = ( accumulatedX + totalX / 2 ) < = maxRight ;
2018-01-22 12:11:36 -08:00
2018-02-08 22:37:58 -08:00
// Widget is visible when no previous sibling has been rejected and its right edge is less than maxRight
widget . Visible = withinLimits ; // widget.Position.X + widget.Width < maxRight;
2018-04-26 07:56:29 -07:00
// Ignore stretched widgets
2018-02-08 22:37:58 -08:00
if ( widget . HAnchor ! = HAnchor . Stretch )
{
accumulatedX + = totalX ;
}
}
2018-01-21 20:45:45 -08:00
}
2022-06-19 15:02:05 -07:00
private void AddMenuItemsFunction ( PopupMenuButton menuButton )
{
menuButton . DynamicPopupContent = ( ) = >
{
var menuTheme = ApplicationController . Instance . MenuTheme ;
var popupMenu = new PopupMenu ( menuTheme ) ;
// Perform overflow
bool hasOverflowItems = false ;
foreach ( var widget in this . ActionArea . Children . Where ( c = > ! c . Visible & & ! ignoredInMenuTypes . Contains ( c . GetType ( ) ) ) )
{
if ( widget is ToolbarSeparator )
{
popupMenu . CreateSeparator ( ) ;
continue ;
}
hasOverflowItems = true ;
PopupMenu . MenuItem menuItem ;
2022-07-16 07:46:44 -07:00
var iconButton = widget as ThemedIconButton ;
2022-06-19 15:02:05 -07:00
var iconImage = iconButton ? . IconImage ;
menuItem = popupMenu . CreateMenuItem (
widget . ToolTipText ? ? widget . Text ,
iconImage ) ;
menuItem . Enabled = widget . Enabled ;
menuItem . Click + = ( s , e ) = >
{
widget . InvokeClick ( ) ;
} ;
}
if ( hasOverflowItems )
{
popupMenu . CreateSeparator ( ) ;
}
// Extend menu with non-overflow/standard items
this . OnExtendPopupMenu ( popupMenu ) ;
return popupMenu ;
} ;
}
2018-01-21 20:45:45 -08:00
/// <summary>
/// A PopupMenuButton with the standard overflow icon
/// </summary>
public class OverflowMenuButton : PopupMenuButton
{
2018-06-23 12:06:46 -07:00
public OverflowMenuButton ( ThemeConfig theme )
2020-08-29 14:12:16 -07:00
: base ( CreateOverflowIcon ( theme ) , theme )
2018-06-23 12:06:46 -07:00
{
}
2021-09-15 17:44:24 -07:00
public OverflowMenuButton ( string text , ThemeConfig theme )
: base ( text , CreateOverflowIcon ( theme ) , theme )
{
}
2018-01-21 20:45:45 -08:00
public OverflowMenuButton ( OverflowBar overflowBar , ThemeConfig theme )
2018-08-29 08:25:59 -07:00
: this ( overflowBar , CreateOverflowIcon ( theme ) , theme )
{
}
public OverflowMenuButton ( OverflowBar overflowBar , ImageBuffer icon , ThemeConfig theme )
: base ( icon , theme )
2022-06-19 15:02:05 -07:00
{
}
2018-01-21 20:45:45 -08:00
2022-06-19 15:02:05 -07:00
private static ImageBuffer CreateOverflowIcon ( ThemeConfig theme )
2018-08-29 08:25:59 -07:00
{
2023-10-03 16:17:01 -07:00
return StaticData . Instance . LoadIcon ( Path . Combine ( "ViewTransformControls" , "overflow.png" ) , 32 , 32 ) . GrayToColor ( theme . TextColor ) ;
2018-08-29 08:25:59 -07:00
}
2018-01-21 20:45:45 -08:00
}
2017-12-26 09:10:42 -08:00
}
}