using FastReport.Utils; using System; using System.Linq; using System.Windows; using System.Windows.Forms; namespace FastReport.Design.RibbonDesigner { internal class Ribbon : StackedPanel { public Designer Designer { get; } public void UpdateLayout() { if (control.ActualWidth == 0) return; var groups = Controls.OfType().ToList(); groups.Sort((x, y) => x.Priority.CompareTo(y.Priority)); double width = this.Measure(); // Collapses a single group. Returns true if a group found Func, Action, bool> Collapse = (condition, action) => { var group = groups.Where(condition).FirstOrDefault(); if (group != null) { var w = group.GroupWidth; action(group); width += group.GroupWidth - w; return true; } return false; }; // Expands a single group. Returns true if a group found and is expanded with success Func, Action, bool> Expand = (condition, action) => { foreach (var group in groups.Where(condition)) { var saveState = group.State; var w = group.GroupWidth; action(group); width += group.GroupWidth - w; // check if we're not exceeding bounds if (width > control.ActualWidth) { // too wide, roll back width -= group.GroupWidth - w; group.State = saveState; } else { return true; } } return false; }; Func ExpandPriority = (priority) => Expand(x => x.State == GroupState.Collapsed && x.Priority == priority, x => x.State = GroupState.Reduced); Func Has = (state) => groups.Where(x => x.State == state).Any(); Func HasPriority = (priority) => groups.Where(x => x.State == GroupState.Collapsed && x.Priority == priority).Any(); while (true) { if (width > control.ActualWidth) { // reduce groups if (Collapse(x => x.State == GroupState.Normal, x => x.State = GroupState.Reduced)) continue; // cannot reduce, try to collapse if (Collapse(x => x.State != GroupState.Collapsed, x => x.State = GroupState.Collapsed)) continue; // everything is in collapsed state, break } else if (width < control.ActualWidth) { // try to expand collapsed groups by priority (high to low). If higher priority groups are not expanded completely, break if (Has(GroupState.Collapsed)) { if (ExpandPriority(GroupPriority.High)) continue; if (!HasPriority(GroupPriority.High)) { if (ExpandPriority(GroupPriority.Medium)) continue; if (!HasPriority(GroupPriority.Medium)) { if (ExpandPriority(GroupPriority.Low)) continue; } } } if (!Has(GroupState.Collapsed)) { // we have no collapsed groups, try to expand reduced groups if (Expand(x => x.State == GroupState.Reduced, x => x.State = GroupState.Normal)) continue; } // nothing to do, break } break; } } public void AddQuickAccessControls(MenuStrip menu) { var qaGroup = new RibbonQuickAccessGroup(Designer); bool compactMenu = Config.UseCompactMenu; menu.Parent.Controls.Insert(0, qaGroup.Panel); var ctl = qaGroup.Panel.control; ctl.Height = 22; ctl.VerticalAlignment = VerticalAlignment.Top; var menuCtl = menu.menu; menuCtl.Padding = new Thickness(5, 0, qaGroup.Panel.Measure(), 0); menuCtl.LayoutUpdated += (s, e) => { var lastItem = menuCtl.Items[menuCtl.Items.Count - 1] as FrameworkElement; var pt = lastItem.TranslatePoint(new Point(lastItem.DesiredSize.Width, 0), menuCtl); if (RightToLeft == RightToLeft.Yes) ctl.Margin = new Thickness(0, compactMenu ? 4 : 1, pt.X + 4, 0); else ctl.Margin = new Thickness(pt.X + 4, compactMenu ? 4 : 1, 0, 0); }; Designer.Plugins.Add(qaGroup); } public Ribbon(Designer designer) { Designer = designer; Vertical = false; control.Margin = new Thickness(4, 0, 0, 0); var stdGroup = new RibbonStandardGroup(designer); Controls.Add(stdGroup); Controls.Add(new ToolStripSeparator(true)); var pageGroup = new RibbonPageGroup(designer); Controls.Add(pageGroup); Controls.Add(new ToolStripSeparator(true)); var editGroup = new RibbonClipboardGroup(designer); Controls.Add(editGroup); Controls.Add(new ToolStripSeparator(true)); var textGroup = new RibbonTextGroup(designer); Controls.Add(textGroup); Controls.Add(new ToolStripSeparator(true)); var borderGroup = new RibbonBorderGroup(designer); Controls.Add(borderGroup); Controls.Add(new ToolStripSeparator(true)); var styleGroup = new RibbonStyleGroup(designer); Controls.Add(styleGroup); Controls.Add(new ToolStripSeparator(true)); var layoutGroup = new RibbonLayoutGroup(designer); Controls.Add(layoutGroup); Controls.Add(new ToolStripSeparator(true)); var polyGroup = new RibbonPolygonGroup(designer); Controls.Add(polyGroup); Designer.Plugins.AddRange(new IDesignerPlugin[] { stdGroup, pageGroup, editGroup, textGroup, borderGroup, styleGroup, layoutGroup, polyGroup }); this.control.SizeChanged += (s, e) => { UpdateLayout(); }; } } }