using System; using System.Drawing; using System.Windows.Forms; using DelftTools.Controls; using DelftTools.Shell.Gui; using DevComponents.DotNetBar; using log4net; namespace DeltaShell.Gui.Forms.ViewManager { /// /// View container works as a facade to DotNetBar incapsulating all logic required to manage 1 view /// including all decoration controls of DotNetBar such as PanelDockContainer, DockContainerItem and /// also providing access to all DotNetBar objects responsible for docking / floating of views, such as: /// Bar, DockSite, etc. /// /// The following classes are involved: /// /// DockSite.............top-level container of dockable bars (left, top, bottom, right, center) /// Bar..................container of one or more PanelDockContainer(s) + DockContainerItem(s) /// PanelDockContainer...actual container of our view control /// DockContainerItem....control containing tab handle with icon, text /// /// Each dock site has the following structure: /// /// DockSite1 /// Bar1 /// DockContainerItem1 /// PanelDockContainer1 <>---- view1 /// DockContainerItem2 /// PanelDockContainer2 <>---- view2 /// Bar2 /// ... /// /// TODO: update text, image from view when it changes /// public class DotNetBarViewContainer : PanelDockContainer { private class ViewDockContainerItem : DockContainerItem { public ViewDockContainerItem(string sName, string ItemText) : base(sName, ItemText) { } protected override void OnBeforeItemRemoved(BaseItem item) { var dotNetBarManager = (DotNetBarManager) (GetOwner()); var bar = dotNetBarManager.GetItemBar(this); LastRemovedItemIndex = bar.Items.IndexOf(this); LastRemovedItemBar = bar; } } /// /// Event fires when the container gets focus (by click or tab or whatever) /// public event EventHandler ViewActivated; private static readonly ILog log = LogManager.GetLogger(typeof (DotNetBarViewContainer)); private IView view; private readonly Control viewControl; private readonly DockContainerItem dockContainerItem; private readonly DotNetBarDockingManager dockingManager; public static int LastRemovedItemIndex { get; set; } public static Bar LastRemovedItemBar { get; set; } public DotNetBarViewContainer(IView view, DotNetBarDockingManager dockingManager, DockSite dockSite) { DevComponents.DotNetBar.ToolTip.MarkupEnabled = false; dockSite.SuspendLayout(); this.view = view; if (string.IsNullOrEmpty(view.Text)) { throw new ArgumentNullException("view", "View must have unique and non-empty text"); } this.dockingManager = dockingManager; viewControl = view as Control;// we expect that view is at least UserControl if (viewControl == null) { throw new ArgumentException("Currently only views derived from Control are supported."); } ColorSchemeStyle = eDotNetBarStyle.VS2005; Name = view.GetType().Name + "_panel"; base.Text = view.Text; SetStyle(); // add viewControl viewControl.Dock = DockStyle.Fill; viewControl.TextChanged += ViewControlTextChanged; Controls.Add(viewControl); Bar bar; // get first or create a new bar and add it to dock site if needed. if (dockSite.Controls.Count > 0) { bar = (Bar) dockSite.Controls[0]; } else { bar = CreateNewDockBar(dockSite, String.Format("bar_{0}", view.Text)); } bar.ThemeAware = false; // create a new DockContainerItem responsible for current view. dockContainerItem = new ViewDockContainerItem(view.Text, view.Text) {Image = view.Image}; //hook up image setter for lockable view if (view is IReusableView) { ((IReusableView) view).IsLockedChanged += (s, e) => { if ( ((IReusableView) view).IsLocked) { if (view.Image != null) { var image = (Image) view.Image.Clone(); AddLockToImage(image); dockContainerItem.Image = image; } else { dockContainerItem.Image = Properties.Resources.lock_edit; } } else { dockContainerItem.Image = view.Image; } }; } // add dockContainerItem to bar bar.Items.Add(dockContainerItem); // set this as a control in a new dock item dockContainerItem.Control = this; if (!dockingManager.Bars.Contains(bar)) { dockingManager.AddBar(dockSite, bar); } dockSite.ResumeLayout(true); bar.RecalcLayout(); Enter += ViewContainer_Enter; Leave += ViewContainer_Leave; GotFocus += ViewContainer_GotFocus; } /* protected override void Dispose(bool disposing) { if (disposing) { if (Bar != null) { Bar.Dispose(); } } base.Dispose(disposing); } */ private static void AddLockToImage(Image image) { Graphics graphics = Graphics.FromImage(image); int height = image.Height; int overlayWidth = height / 2;//covers 2/3 of the image int overlayHeight = height*2/3; graphics.DrawImage(Properties.Resources.lock_edit, 0, height - overlayHeight, overlayWidth, overlayHeight); graphics.Dispose(); } private void SetStyle() { Style.BackColor1.ColorSchemePart = eColorSchemePart.BarBackground; Style.BackColor2.ColorSchemePart = eColorSchemePart.BarBackground2; Style.BorderColor.ColorSchemePart = eColorSchemePart.BarDockedBorder; Style.ForeColor.ColorSchemePart = eColorSchemePart.ItemText; Style.GradientAngle = 90; } internal Bar Bar { get { return dockContainerItem.ContainerControl as Bar; } } void ViewContainer_GotFocus(object sender, EventArgs e) { FireViewActivated(); } private void ViewContainer_Enter(object sender, EventArgs e) { // update context menu for new bars if (Bar != null && Bar.DockTabControl != null) { Bar.DockTabControl.CloseButtonOnTabsVisible = true; Bar.DockTabControl.CloseButtonPosition = eTabCloseButtonPosition.Right; Bar.DockTabControl.TabCloseButtonNormal = Properties.Resources.cross_small_bw; Bar.DockTabControl.TabCloseButtonHot = Properties.Resources.cross_small; Bar.DockTabControl.AntiAlias = true; Bar.DockTabControl.SelectedTabFont = new Font(Bar.DockTabControl.Font, FontStyle.Italic); Bar.DockTabControl.TabLayoutType = eTabLayoutType.FixedWithNavigationBox; } // Enter event is also fired from controls which are not visible yet, then we should not switch active view if (!Visible) { return; } SetFocusToChildControlUnderMouseLocation(); FireViewActivated(); } /// /// Sets focus to the inner-most child control of the view . /// private void SetFocusToChildControlUnderMouseLocation() { var position = System.Windows.Forms.Cursor.Position; var childControl = GetInnerMostChildControl(position, viewControl); if(childControl != null) { childControl.Select(); } } Control GetInnerMostChildControl(Point position, Control parentControl) { var localPosition = parentControl.PointToClient(position); var childControl = parentControl.GetChildAtPoint(localPosition); if(childControl != null) { return GetInnerMostChildControl(position, childControl); } return parentControl; } private void ViewContainer_Leave(object sender, EventArgs e) { } private void FireViewActivated() { if (ViewActivated != null) { ViewActivated(this, new ViewEventArgs { View = view }); } } public IView View { get { return view; } set { view = value; } } public string Tooltip { get { return DockContainerItem.Tooltip; } set { if (!string.IsNullOrEmpty(value)) { DockContainerItem.Tooltip = value.Replace('\\', ':'); } } } public event DotNetBarManager.DockTabChangeEventHandler DockTabChanged; public void Remove(bool removeTabFromDockingBar) { viewControl.TextChanged -= ViewControlTextChanged; // remove dock item from the current bar Bar bar = dockContainerItem.ContainerControl as Bar; if (bar != null) { //boolean is needed because if we get a close from barclosing (the user clicks top right x) the tab will //already be removed by dotnetbar if (removeTabFromDockingBar) { bar.Items.Remove(dockContainerItem); } // get rid of bar if it is empty if (bar.Items.Count == 0 && dockingManager.Bars != null) { // bar.DockedSite.Controls.Remove(bar); dockingManager.RemoveBar(bar); /* bar.Dispose(); */ // dockingManager.Bars.Remove(bar); } } //view.Dispose(); } /// /// Activates this view container /// public void Activate() { log.DebugFormat("Activating view '{0}'", view.Text); var bar = dockContainerItem.ContainerControl as Bar; if (bar == null) return; var control = (Control)view; if (!control.Visible) { control.Show(); } control.Select(); if (bar.AutoHide) { bar.AutoHideVisible = true; } else { bar.Visible = true; } bar.SelectedDockTab = bar.Items.IndexOf(DockContainerItem); dockContainerItem.Focus(); } /// /// Creates a new Bar which can host multiple ViewContainers/Views. /// /// private static Bar CreateNewDockBar(DockSite dockSite, string name) { log.DebugFormat("Creating a new view '{0}' in dockSite: {1}", name, dockSite); Bar bar = new Bar(); bar.Name = name; bar.AccessibleRole = System.Windows.Forms.AccessibleRole.ToolBar; bar.LayoutType = eLayoutType.DockContainer; bar.Stretch = true; bar.Style = eDotNetBarStyle.VS2005; bar.AutoHideAnimationTime = 0; // Some controls do not support animation so turn it off bar.AutoHideVisible = true; if (dockSite.Owner.FillDockSite == dockSite) //Docksite is in the center { bar.AlwaysDisplayDockTab = true; bar.CanCustomize = false; bar.CanDockBottom = false; bar.CanDockDocument = true; bar.CanDockLeft = false; bar.CanDockRight = false; bar.CanDockTop = false; bar.CanHide = true; bar.CanUndock = false; bar.DockTabAlignment = eTabStripAlignment.Top; bar.TabNavigation = true; } else { bar.AutoSyncBarCaption = true; bar.CloseSingleTab = true; bar.GrabHandleStyle = eGrabHandleStyle.Caption; bar.CanHide = true; } return bar; } // TODO: rely on view to get event instead of control private void ViewControlTextChanged(object sender, EventArgs e) { dockContainerItem.Text = view.Text; dockContainerItem.Name = view.Text; } } }