using System; using System.ComponentModel; using System.Linq; using System.Windows.Forms; using FastReport.Design; using FastReport.Utils; namespace FastReport.Controls { internal class FRSideControl : Panel { private UIStyle style; private Designer designer; private Splitter splitter; private ControlStorageService storage; /// /// Gets storage service. /// public ControlStorageService Storage { get { if (storage == null) storage = new ControlStorageService(this, "Designer," + Name); return storage; } } public FRTabControl TopPanel { get; } public FRTabControl BottomPanel { get; } public UIStyle Style { get => style; set { style = value; var table = UIStyleUtils.GetColorTable(value); TopPanel.Style = BottomPanel.Style = table.ToolWindow; splitter.BackColor = table.Workspace.SplitterBackColor; } } public FRSideControl OtherSideControl { get; set; } public bool IsEmpty => VisiblePanelCount == 0; public event EventHandler LayoutChanged; private int VisiblePanelCount => (TopPanel.Tabs.Count > 0 ? 1 : 0) + (BottomPanel.Tabs.Count > 0 ? 1 : 0); private string GetControls(FRTabControl panel) => string.Join(",", panel.Tabs.Cast().Select(c => c.Name)); private void SetControls(FRTabControl panel, string controls) { panel.Tabs.Clear(); foreach (var name in controls.Split(',')) { var plugin = designer.Plugins.Find(name) as PageControlPage; if (plugin != null) { plugin.Dock = DockStyle.Fill; panel.Tabs.Add(plugin); } } } private void topPanelMenu_Opening(object sender, CancelEventArgs e) { TopPanel.Menu.Items.Clear(); TopPanel.Menu.Font = this.Font; var selectedTab = TopPanel.SelectedTab; var selectedTabText = "\"" + selectedTab.Text + "\""; var res = new MyRes("Designer,ToolWindow"); var menuDockToBottom = new ToolStripMenuItem(string.Format(res.Get("DockToBottom"), selectedTabText)); menuDockToBottom.Click += (s, args) => { AddToBottomPanel(selectedTab); RefreshLayout(); }; if (VisiblePanelCount > 1 || TopPanel.Tabs.Count > 1) TopPanel.Menu.Items.Add(menuDockToBottom); var menuDockToOtherSide = new ToolStripMenuItem(string.Format(res.Get("DockToOtherSide"), selectedTabText)); menuDockToOtherSide.Click += (s, args) => { OtherSideControl.AddToTopPanel(selectedTab); RefreshLayout(); OtherSideControl.RefreshLayout(); }; TopPanel.Menu.Items.Add(menuDockToOtherSide); } private void bottomPanelMenu_Opening(object sender, CancelEventArgs e) { BottomPanel.Menu.Items.Clear(); BottomPanel.Menu.Font = this.Font; var selectedTab = BottomPanel.SelectedTab; var selectedTabText = "\"" + selectedTab.Text + "\""; var res = new MyRes("Designer,ToolWindow"); var menuDockToTop = new ToolStripMenuItem(string.Format(res.Get("DockToTop"), selectedTabText)); menuDockToTop.Click += (s, args) => { AddToTopPanel(selectedTab); RefreshLayout(); }; if (VisiblePanelCount > 1 || BottomPanel.Tabs.Count > 1) BottomPanel.Menu.Items.Add(menuDockToTop); var menuDockToOtherSide = new ToolStripMenuItem(string.Format(res.Get("DockToOtherSide"), selectedTabText)); menuDockToOtherSide.Click += (s, args) => { OtherSideControl.AddToBottomPanel(selectedTab); RefreshLayout(); OtherSideControl.RefreshLayout(); }; BottomPanel.Menu.Items.Add(menuDockToOtherSide); } private void AddToPanel(FRTabControl panel, PageControlPage page) { page.Dock = DockStyle.Fill; panel.Tabs.Add(page); // workaround SWF behavior (page is added somewhere in the middle of the Controls list) page.SendToBack(); } public void AddToTopPanel(PageControlPage page) => AddToPanel(TopPanel, page); public void AddToBottomPanel(PageControlPage page) => AddToPanel(BottomPanel, page); public void RefreshLayout() { bool splitterWasVisible = splitter.Visible; TopPanel.Visible = TopPanel.Tabs.Count > 0; BottomPanel.Visible = BottomPanel.Tabs.Count > 0; splitter.Visible = VisiblePanelCount == 2; TopPanel.Dock = BottomPanel.Tabs.Count > 0 ? DockStyle.Top : DockStyle.Fill; if (!splitterWasVisible && splitter.Visible) TopPanel.Height = Height / 2; TopPanel.Refresh(); TopPanel.SelectedTabIndex = 0; BottomPanel.Refresh(); BottomPanel.SelectedTabIndex = 0; LayoutChanged?.Invoke(this, EventArgs.Empty); } public void UpdateDpiDependencies() { TopPanel.UpdateDpiDependencies(); BottomPanel.UpdateDpiDependencies(); splitter.Height = this.LogicalToDevice(3); } public void UpdateText() { TopPanel.UpdateText(); BottomPanel.UpdateText(); } public void SaveState() { Storage.SetDip("Width", Width); Storage.SetDip("TopPanelHeight", Math.Min(TopPanel.Height, Height - 50)); Storage.SetStr("TopPanelControls", GetControls(TopPanel)); Storage.SetStr("BottomPanelControls", GetControls(BottomPanel)); } public void RestoreState() { if (Storage.HasProperties) { Width = Storage.GetDip("Width", 280, 50, 1000); SetControls(TopPanel, Storage.GetStr("TopPanelControls")); SetControls(BottomPanel, Storage.GetStr("BottomPanelControls")); RefreshLayout(); TopPanel.Height = Storage.GetDip("TopPanelHeight", 350); } } public FRSideControl(Designer designer) { this.designer = designer; Name = "SideControl"; TopPanel = new FRTabControl(); TopPanel.Dock = DockStyle.Top; TopPanel.CloseButtons = false; TopPanel.Menu = new ContextMenuStrip(); TopPanel.Menu.Items.Add(new ToolStripMenuItem("dummy")); TopPanel.Menu.Opening += topPanelMenu_Opening; BottomPanel = new FRTabControl(); BottomPanel.Dock = DockStyle.Fill; BottomPanel.CloseButtons = false; BottomPanel.Menu = new ContextMenuStrip(); BottomPanel.Menu.Items.Add(new ToolStripMenuItem("dummy")); BottomPanel.Menu.Opening += bottomPanelMenu_Opening; splitter = new Splitter(); splitter.Dock = DockStyle.Top; splitter.MinSize = 0; splitter.MinExtra = 0; Controls.AddRange(new Control[] { BottomPanel, splitter, TopPanel }); } } }