using System; using System.Collections.Generic; using System.Windows.Forms; using System.Drawing; using FastReport.Utils; using FastReport.Forms; namespace FastReport.Design { internal class ObjectsToolbar : ToolStrip, IDesignerPlugin { #region Fields private Size buttonSize; private Report currentReport; private PageBase currentPage; private ObjectInfo nowInserting; public ToolStripButton btnSelect; private Dictionary> cachedButtons = new Dictionary>(); #endregion #region Properties internal Designer Designer { get; } /// public string PluginName => Name; #endregion #region Private Methods private void DoCreateButtons(ObjectInfo rootItem, bool forceCreate) { var pageType = rootItem.Object; if (!forceCreate && cachedButtons.ContainsKey(pageType)) { GetCachedButtons(pageType); } else { DoCreateButtons(rootItem); CacheButtons(pageType); } } private void DoCreateButtons(ObjectInfo rootItem) { foreach (ObjectInfo item in rootItem.Items) { if (item.Items.Count == 0) { // it's an object ToolStripButton button = new ToolStripButton(); button.AutoSize = false; button.Size = buttonSize; button.Image = this.GetImage(item.ImageIndex); button.ToolTipText = Res.TryGet(item.Text); button.Tag = item; button.Click += button_Click; Items.Add(button); } else { // it's a category ToolStripDropDownButton button = new ToolStripDropDownButton(); button.Image = this.GetImage(item.ImageIndex); button.ToolTipText = Res.TryGet(item.Text); button.Tag = item; button.ShowDropDownArrow = false; button.AutoSize = false; button.Size = buttonSize; DoCreateMenus(item, button.DropDownItems); Items.Add(button); } } SortButtons(Items); } private void DoCreateMenus(ObjectInfo rootItem, ToolStripItemCollection items) { foreach (ObjectInfo item in rootItem.Items) { ToolStripMenuItem menuItem = new ToolStripMenuItem(); menuItem.Image = this.GetImage(item.ImageIndex); menuItem.Text = Res.TryGet(item.Text); menuItem.Tag = item; menuItem.Font = DrawUtils.DefaultFont; items.Add(menuItem); if (item.Items.Count != 0) { // it's a category DoCreateMenus(item, menuItem.DropDownItems); } else { menuItem.Click += button_Click; } } SortButtons(items); } private void CreateSelectBtn() { btnSelect = new ToolStripButton(); btnSelect.AutoSize = false; btnSelect.Size = buttonSize; btnSelect.Image = this.GetImage(100); btnSelect.ToolTipText = Res.Get("Designer,Toolbar,Objects,Select"); btnSelect.Click += btnSelect_Click; Items.Add(btnSelect); } private void SortButtons(ToolStripItemCollection root) { List tempItems = new List(); List lastItems = new List(); tempItems.Add(root[0]); for (int i = 1; i < root.Count; i++) { for (int j = 1; j < root.Count; j++) { ObjectInfo objInfo = (root[j] as ToolStripItem).Tag as ObjectInfo; if (objInfo != null) { if (objInfo.ButtonIndex == i) { tempItems.Add(root[j]); } if (objInfo.ButtonIndex < 0 || objInfo.ButtonIndex >= root.Count) { lastItems.Add(root[j]); } } } } root.Clear(); root.AddRange(tempItems.ToArray()); root.AddRange(lastItems.ToArray()); } private void CacheButtons(Type pageType) { var dictEntry = new List(); foreach (ToolStripItem item in Items) { if (item != btnSelect) dictEntry.Add(item); } cachedButtons[pageType] = dictEntry; } private void GetCachedButtons(Type pageType) { var dictEntry = cachedButtons[pageType]; foreach (var item in dictEntry) { Items.Add(item); } } private void CreateButtons(bool forceCreate = false) { if (!forceCreate && Designer.ActiveReport != null && Designer.ActiveReport == currentReport && Designer.ActiveReportTab.ActivePage == currentPage) return; currentReport = Designer.ActiveReport; if (Designer.ActiveReportTab != null) currentPage = Designer.ActiveReportTab.ActivePage; else currentPage = null; // delete all buttons except btnSelect int i = 0; while (i < Items.Count) { if (!forceCreate && Items[i] == btnSelect) i++; else { Items.RemoveAt(i); } } if (forceCreate) CreateSelectBtn(); // create object buttons ObjectInfo pageItem = RegisteredObjects.FindObject(currentPage); if (pageItem != null) { DoCreateButtons(pageItem, forceCreate); } } private void button_Click(object sender, EventArgs e) { Designer.FormatPainter = false; if (!Designer.cmdInsert.Enabled) return; ResetButtons(); if (sender is ToolStripButton btn) btn.Checked = true; nowInserting = (sender as ToolStripItem).Tag as ObjectInfo; Designer.InsertObject(nowInserting, InsertFrom.NewObject); } private void btnSelect_Click(object sender, EventArgs e) { Designer.FormatPainter = false; if (Designer.ActiveReportTab == null) return; DoClickSelectButton(true); } private void DoClickSelectButton(bool ignoreMultiInsert) { if (!btnSelect.Checked) { if (nowInserting != null && nowInserting.MultiInsert && !ignoreMultiInsert) { Designer.InsertObject(nowInserting, InsertFrom.NewObject); } else { ResetButtons(); btnSelect.Checked = true; Designer.CancelPaste(); } } } private void ResetButtons() { foreach (ToolStripItem item in Items) { if (item is ToolStripButton btn) btn.Checked = false; } } #endregion #region Public Methods public void ClickSelectButton(bool ignoreMultiInsert) { DoClickSelectButton(ignoreMultiInsert); } #endregion #region IDesignerPlugin /// public void SaveState() { } /// public void RestoreState() { } /// public void SelectionChanged() { CreateButtons(); } /// public void UpdateContent() { CreateButtons(); } /// public void Lock() { } /// public void Unlock() { UpdateContent(); } /// public void Localize() { MyRes res = new MyRes("Designer,Toolbar,Objects"); Text = res.Get(""); btnSelect.ToolTipText = res.Get("Select"); } /// public DesignerOptionsPage GetOptionsPage() { return null; } /// public void UpdateUIStyle() { Renderer = UIStyleUtils.GetToolStripRenderer(Designer.UIStyle); } /// public void UpdateDpiDependencies() { Font = this.LogicalToDevice(DrawUtils.DefaultFont); Width = Designer.LogicalToDevice(30); CreateButtons(true); } #endregion public ObjectsToolbar(Designer designer) : base() { Designer = designer; Name = "ObjectsToolbar"; Dock = DockStyle.Left; GripStyle = ToolStripGripStyle.Hidden; AutoSize = false; // WPF specific: button size with the default dpi setting. // On a multi-monitor system buttons will scale automatically buttonSize = this.LogicalToDevice(new Size(23, 23)); if (Config.IsRunningOnMono) Padding = new Padding(1, 0, 0, 0); #if (WPF || AVALONIA) BorderThickness = new Padding(0, 0, 1, 0); #endif Parent = Designer; UpdateDpiDependencies(); Localize(); } } }