Ribbon.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. using FastReport.Utils;
  2. using System;
  3. using System.Linq;
  4. using System.Windows;
  5. using System.Windows.Forms;
  6. namespace FastReport.Design.RibbonDesigner
  7. {
  8. internal class Ribbon : StackedPanel
  9. {
  10. public Designer Designer { get; }
  11. public void UpdateLayout()
  12. {
  13. if (control.ActualWidth == 0)
  14. return;
  15. var groups = Controls.OfType<RibbonGroup>().ToList();
  16. groups.Sort((x, y) => x.Priority.CompareTo(y.Priority));
  17. double width = this.Measure();
  18. // Collapses a single group. Returns true if a group found
  19. Func<Func<RibbonGroup, bool>, Action<RibbonGroup>, bool> Collapse = (condition, action) =>
  20. {
  21. var group = groups.Where(condition).FirstOrDefault();
  22. if (group != null)
  23. {
  24. var w = group.GroupWidth;
  25. action(group);
  26. width += group.GroupWidth - w;
  27. return true;
  28. }
  29. return false;
  30. };
  31. // Expands a single group. Returns true if a group found and is expanded with success
  32. Func<Func<RibbonGroup, bool>, Action<RibbonGroup>, bool> Expand = (condition, action) =>
  33. {
  34. foreach (var group in groups.Where(condition))
  35. {
  36. var saveState = group.State;
  37. var w = group.GroupWidth;
  38. action(group);
  39. width += group.GroupWidth - w;
  40. // check if we're not exceeding bounds
  41. if (width > control.ActualWidth)
  42. {
  43. // too wide, roll back
  44. width -= group.GroupWidth - w;
  45. group.State = saveState;
  46. }
  47. else
  48. {
  49. return true;
  50. }
  51. }
  52. return false;
  53. };
  54. Func<GroupPriority, bool> ExpandPriority = (priority) => Expand(x => x.State == GroupState.Collapsed && x.Priority == priority, x => x.State = GroupState.Reduced);
  55. Func<GroupState, bool> Has = (state) => groups.Where(x => x.State == state).Any();
  56. Func<GroupPriority, bool> HasPriority = (priority) => groups.Where(x => x.State == GroupState.Collapsed && x.Priority == priority).Any();
  57. while (true)
  58. {
  59. if (width > control.ActualWidth)
  60. {
  61. // reduce groups
  62. if (Collapse(x => x.State == GroupState.Normal, x => x.State = GroupState.Reduced))
  63. continue;
  64. // cannot reduce, try to collapse
  65. if (Collapse(x => x.State != GroupState.Collapsed, x => x.State = GroupState.Collapsed))
  66. continue;
  67. // everything is in collapsed state, break
  68. }
  69. else if (width < control.ActualWidth)
  70. {
  71. // try to expand collapsed groups by priority (high to low). If higher priority groups are not expanded completely, break
  72. if (Has(GroupState.Collapsed))
  73. {
  74. if (ExpandPriority(GroupPriority.High))
  75. continue;
  76. if (!HasPriority(GroupPriority.High))
  77. {
  78. if (ExpandPriority(GroupPriority.Medium))
  79. continue;
  80. if (!HasPriority(GroupPriority.Medium))
  81. {
  82. if (ExpandPriority(GroupPriority.Low))
  83. continue;
  84. }
  85. }
  86. }
  87. if (!Has(GroupState.Collapsed))
  88. {
  89. // we have no collapsed groups, try to expand reduced groups
  90. if (Expand(x => x.State == GroupState.Reduced, x => x.State = GroupState.Normal))
  91. continue;
  92. }
  93. // nothing to do, break
  94. }
  95. break;
  96. }
  97. }
  98. public void AddQuickAccessControls(MenuStrip menu)
  99. {
  100. var qaGroup = new RibbonQuickAccessGroup(Designer);
  101. bool compactMenu = Config.UseCompactMenu;
  102. menu.Parent.Controls.Insert(0, qaGroup.Panel);
  103. var ctl = qaGroup.Panel.control;
  104. ctl.Height = 22;
  105. ctl.VerticalAlignment = VerticalAlignment.Top;
  106. var menuCtl = menu.menu;
  107. menuCtl.Padding = new Thickness(5, 0, qaGroup.Panel.Measure(), 0);
  108. menuCtl.LayoutUpdated += (s, e) =>
  109. {
  110. var lastItem = menuCtl.Items[menuCtl.Items.Count - 1] as FrameworkElement;
  111. var pt = lastItem.TranslatePoint(new Point(lastItem.DesiredSize.Width, 0), menuCtl);
  112. if (RightToLeft == RightToLeft.Yes)
  113. ctl.Margin = new Thickness(0, compactMenu ? 4 : 1, pt.X + 4, 0);
  114. else
  115. ctl.Margin = new Thickness(pt.X + 4, compactMenu ? 4 : 1, 0, 0);
  116. };
  117. Designer.Plugins.Add(qaGroup);
  118. }
  119. public Ribbon(Designer designer)
  120. {
  121. Designer = designer;
  122. Vertical = false;
  123. control.Margin = new Thickness(4, 0, 0, 0);
  124. var stdGroup = new RibbonStandardGroup(designer);
  125. Controls.Add(stdGroup);
  126. Controls.Add(new ToolStripSeparator(true));
  127. var pageGroup = new RibbonPageGroup(designer);
  128. Controls.Add(pageGroup);
  129. Controls.Add(new ToolStripSeparator(true));
  130. var editGroup = new RibbonClipboardGroup(designer);
  131. Controls.Add(editGroup);
  132. Controls.Add(new ToolStripSeparator(true));
  133. var textGroup = new RibbonTextGroup(designer);
  134. Controls.Add(textGroup);
  135. Controls.Add(new ToolStripSeparator(true));
  136. var borderGroup = new RibbonBorderGroup(designer);
  137. Controls.Add(borderGroup);
  138. Controls.Add(new ToolStripSeparator(true));
  139. var styleGroup = new RibbonStyleGroup(designer);
  140. Controls.Add(styleGroup);
  141. Controls.Add(new ToolStripSeparator(true));
  142. var layoutGroup = new RibbonLayoutGroup(designer);
  143. Controls.Add(layoutGroup);
  144. Controls.Add(new ToolStripSeparator(true));
  145. var polyGroup = new RibbonPolygonGroup(designer);
  146. Controls.Add(polyGroup);
  147. Designer.Plugins.AddRange(new IDesignerPlugin[] {
  148. stdGroup, pageGroup, editGroup, textGroup, borderGroup, styleGroup, layoutGroup, polyGroup });
  149. this.control.SizeChanged += (s, e) =>
  150. {
  151. UpdateLayout();
  152. };
  153. }
  154. }
  155. }