Example #1
4
        /// <summary>Internal method for rendering an individual <paramref name="tab" /> to the screen.</summary>
        /// <param name="graphicsContext">Graphics context to use when rendering the tab.</param>
        /// <param name="tab">Individual tab that we are to render.</param>
        /// <param name="area">Area of the screen that the tab should be rendered to.</param>
        /// <param name="cursor">Current position of the cursor.</param>
        protected virtual void Render(Graphics graphicsContext, TitleBarTab tab, Rectangle area, Point cursor)
        {
            if (_suspendRendering)
            {
                return;
            }

            // If we need to redraw the tab image
            if (tab.TabImage == null)
            {
                // We render the tab to an internal property so that we don't necessarily have to redraw it in every rendering pass, only if its width or
                // status have changed
                tab.TabImage = new Bitmap(
                    area.Width, tab.Active
                        ? _activeCenterImage.Height
                        : _inactiveCenterImage.Height);

                using (Graphics tabGraphicsContext = Graphics.FromImage(tab.TabImage))
                {
                    // Draw the left, center, and right portions of the tab
                    tabGraphicsContext.DrawImage(
                        tab.Active
                            ? _activeLeftSideImage
                            : _inactiveLeftSideImage, new Rectangle(
                                0, 0, tab.Active
                                    ? _activeLeftSideImage
                                        .Width
                                    : _inactiveLeftSideImage
                                        .Width,
                                tab.Active
                                    ? _activeLeftSideImage.
                                        Height
                                    : _inactiveLeftSideImage
                                        .Height), 0, 0,
                        tab.Active
                            ? _activeLeftSideImage.Width
                            : _inactiveLeftSideImage.Width, tab.Active
                                ? _activeLeftSideImage.Height
                                : _inactiveLeftSideImage.Height,
                        GraphicsUnit.Pixel);

                    tabGraphicsContext.DrawImage(
                        tab.Active
                            ? _activeCenterImage
                            : _inactiveCenterImage, new Rectangle(
                                (tab.Active
                                    ? _activeLeftSideImage.
                                        Width
                                    : _inactiveLeftSideImage
                                        .Width), 0,
                                _tabContentWidth, tab.Active
                                    ? _activeCenterImage
                                        .
                                        Height
                                    : _inactiveCenterImage
                                        .
                                        Height),
                        0, 0, _tabContentWidth, tab.Active
                            ? _activeCenterImage.Height
                            : _inactiveCenterImage.Height,
                        GraphicsUnit.Pixel);

                    tabGraphicsContext.DrawImage(
                        tab.Active
                            ? _activeRightSideImage
                            : _inactiveRightSideImage, new Rectangle(
                                (tab.Active
                                    ? _activeLeftSideImage
                                        .Width
                                    : _inactiveLeftSideImage
                                        .Width) +
                                _tabContentWidth, 0,
                                tab.Active
                                    ? _activeRightSideImage
                                        .Width
                                    : _inactiveRightSideImage
                                        .Width,
                                tab.Active
                                    ? _activeRightSideImage
                                        .Height
                                    : _inactiveRightSideImage
                                        .Height), 0, 0,
                        tab.Active
                            ? _activeRightSideImage.Width
                            : _inactiveRightSideImage.Width, tab.Active
                                ? _activeRightSideImage.Height
                                : _inactiveRightSideImage.
                                    Height,
                        GraphicsUnit.Pixel);

                    // Draw the close button
                    if (tab.ShowCloseButton)
                    {
                        Image closeButtonImage = IsOverCloseButton(tab, cursor)
                            ? _closeButtonHoverImage
                            : _closeButtonImage;

                        tab.CloseButtonArea = new Rectangle(
                            area.Width - (tab.Active
                                ? _activeRightSideImage.Width
                                : _inactiveRightSideImage.Width) -
                            CloseButtonMarginRight - closeButtonImage.Width,
                            CloseButtonMarginTop, closeButtonImage.Width,
                            closeButtonImage.Height);

                        tabGraphicsContext.DrawImage(
                            closeButtonImage, tab.CloseButtonArea, 0, 0,
                            closeButtonImage.Width, closeButtonImage.Height,
                            GraphicsUnit.Pixel);
                    }
                }

                tab.Area = area;
            }

            // Render the tab's saved image to the screen
            graphicsContext.DrawImage(
                tab.TabImage, area, 0, 0, tab.TabImage.Width, tab.TabImage.Height,
                GraphicsUnit.Pixel);

            // Render the icon for the tab's content, if it exists and there's room for it in the tab's content area
            if (tab.Content.ShowIcon && _tabContentWidth > 16 + IconMarginLeft + (tab.ShowCloseButton
                ? CloseButtonMarginLeft +
                  tab.CloseButtonArea.Width +
                  CloseButtonMarginRight
                : 0))
            {
                graphicsContext.DrawIcon(
                    new Icon(tab.Content.Icon, 16, 16),
                    new Rectangle(area.X + OverlapWidth + IconMarginLeft, IconMarginTop + area.Y, 16, 16));
            }

            // Render the caption for the tab's content if there's room for it in the tab's content area
            if (_tabContentWidth > (tab.Content.ShowIcon
                ? 16 + IconMarginLeft + IconMarginRight
                : 0) + CaptionMarginLeft + CaptionMarginRight + (tab.ShowCloseButton
                    ? CloseButtonMarginLeft +
                      tab.CloseButtonArea.Width +
                      CloseButtonMarginRight
                    : 0))
            {
                graphicsContext.DrawString(
                    tab.Caption, SystemFonts.CaptionFont, Brushes.Black,
                    new Rectangle(
                        area.X + OverlapWidth + CaptionMarginLeft + (tab.Content.ShowIcon
                            ? IconMarginLeft +
                              16 +
                              IconMarginRight
                            : 0),
                        CaptionMarginTop + area.Y,
                        _tabContentWidth - (tab.Content.ShowIcon
                            ? IconMarginLeft + 16 + IconMarginRight
                            : 0) - (tab.ShowCloseButton
                                ? _closeButtonImage.Width +
                                  CloseButtonMarginRight +
                                  CloseButtonMarginLeft
                                : 0), tab.TabImage.Height),
                    new StringFormat(StringFormatFlags.NoWrap)
                    {
                        Trimming = StringTrimming.EllipsisCharacter
                    });
            }
        }
Example #2
1
        private void CloseTab(TitleBarTab clickedTab)
        {
            if (_parentForm.AutoCloseTab)
            {
                clickedTab.Content.Close();
            }

            _parentForm.OnTabClosed(
                new TitleBarTabEventArgs
            {
                Tab         = clickedTab,
                TabIndex    = _parentForm.SelectedTabIndex,
                Action      = null,
                WasDragging = false
            });
        }
Example #3
1
        /// <summary>
        /// Called when a torn tab is dragged into the <see cref="TitleBarTabs.TabDropArea" /> of <see cref="_parentWindow" />.  Places the tab in the list and
        /// sets <see cref="IsTabRepositioning" /> to true to simulate the user continuing to drag the tab around in the window.
        /// </summary>
        /// <param name="tab">Tab that was dragged into this window.</param>
        /// <param name="cursorLocation">Location of the user's cursor.</param>
        internal virtual void CombineTab(TitleBarTab tab, Point cursorLocation)
        {
            // Stop rendering to prevent weird stuff from happening like the wrong tab being focused
            _suspendRendering = true;

            // Find out where to insert the tab in the list
            int dropIndex = _parentWindow.Tabs.FindIndex(t => t.Area.Left <= cursorLocation.X && t.Area.Right >= cursorLocation.X);

            // Simulate the user having clicked in the middle of the tab when they started dragging it so that the tab will move correctly within the window
            // when the user continues to move the mouse
            if (_parentWindow.Tabs.Count > 0)
            {
                _tabClickOffset = _parentWindow.Tabs.First().Area.Width / 2;
            }
            else
            {
                _tabClickOffset = 0;
            }
            IsTabRepositioning = true;

            tab.Parent = _parentWindow;

            if (dropIndex == -1)
            {
                _parentWindow.Tabs.Add(tab);
                dropIndex = _parentWindow.Tabs.Count - 1;
            }

            else
            {
                _parentWindow.Tabs.Insert(dropIndex, tab);
            }

            // Resume rendering
            _suspendRendering = false;

            _parentWindow.SelectedTabIndex = dropIndex;
            _parentWindow.ResizeTabContents();
        }
Example #4
0
        /// <summary>Callback that is invoked whenever anything is added or removed from <see cref="Tabs" /> so that we can trigger a redraw of the tabs.</summary>
        /// <param name="sender">Object for which this event was raised.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void _tabs_CollectionModified(object sender, ListModificationEventArgs e)
        {
            SetFrameSize();

            if (e.Modification == ListModification.ItemAdded || e.Modification == ListModification.RangeAdded)
            {
                for (int i = 0; i < e.Count; i++)
                {
                    TitleBarTab currentTab = Tabs[i + e.StartIndex];

                    currentTab.Content.TextChanged += Content_TextChanged;
                    currentTab.Closing             += TitleBarTabs_Closing;

                    if (AeroPeekEnabled)
                    {
                        TaskbarManager.Instance.TabbedThumbnail.SetActiveTab(CreateThumbnailPreview(currentTab));
                    }
                }
            }

            if (_overlay != null)
            {
                _overlay.Render(true);
            }
        }
Example #5
0
        /// <summary>
        /// Creates a new thumbnail for <paramref name="tab" /> when the application is initially enabled for AeroPeek or when it is turned on sometime during
        /// execution.
        /// </summary>
        /// <param name="tab">Tab that we are to create the thumbnail for.</param>
        /// <returns>Thumbnail created for <paramref name="tab" />.</returns>
        protected virtual TabbedThumbnail CreateThumbnailPreview(TitleBarTab tab)
        {
            TabbedThumbnail preview = TaskbarManager.Instance.TabbedThumbnail.GetThumbnailPreview(tab.Content);

            if (preview != null)
            {
                TaskbarManager.Instance.TabbedThumbnail.RemoveThumbnailPreview(tab.Content);
            }

            preview = new TabbedThumbnail(Handle, tab.Content)
            {
                Title   = tab.Content.Text,
                Tooltip = tab.Content.Text
            };

            preview.SetWindowIcon((Icon)tab.Content.Icon.Clone());

            preview.TabbedThumbnailActivated       += preview_TabbedThumbnailActivated;
            preview.TabbedThumbnailClosed          += preview_TabbedThumbnailClosed;
            preview.TabbedThumbnailBitmapRequested += preview_TabbedThumbnailBitmapRequested;
            preview.PeekOffset = new Vector(Padding.Left, Padding.Top - 1);

            TaskbarManager.Instance.TabbedThumbnail.AddThumbnailPreview(preview);

            return(preview);
        }
Example #6
0
 public TitleBarTabEventArgs(TabControlAction?action, TitleBarTab tab, int tabIndex, bool wasDragging)
 {
     Action      = action;
     Tab         = tab;
     TabIndex    = tabIndex;
     WasDragging = wasDragging;
 }
        private void ShowTooltipTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (!_parentForm.ShowTooltips)
            {
                return;
            }

            Point       relativeCursorPosition = GetRelativeCursorPosition(Cursor.Position);
            TitleBarTab hoverTab = _parentForm.TabRenderer.OverTab(_parentForm.Tabs, relativeCursorPosition);

            if (hoverTab != null)
            {
                TitleBarTabs hoverTabForm = hoverTab.Parent;

                if (hoverTabForm.InvokeRequired)
                {
                    hoverTabForm.Invoke(new Action(() =>
                    {
                        ShowTooltip(hoverTabForm, hoverTab.Caption);
                    }));
                }

                else
                {
                    ShowTooltip(hoverTabForm, hoverTab.Caption);
                }
            }
        }
Example #8
0
        /// <summary>Calls <see cref="CreateTab" />, adds the resulting tab to the <see cref="Tabs" /> collection, and activates it.</summary>
        public virtual void AddNewTab()
        {
            TitleBarTab newTab = CreateTab();

            Tabs.Add(newTab);
            ResizeTabContents(newTab);

            SelectedTabIndex = _tabs.Count - 1;
        }
Example #9
0
        protected override void Render(Graphics graphicsContext, TitleBarTab tab, int index, Rectangle area, Point cursor, Image tabLeftImage, Image tabCenterImage, Image tabRightImage)
        {
            if (!IsWindows10 && !tab.Active && index == _parentWindow.Tabs.Count - 1)
            {
                tabRightImage = Resources.ChromeInactiveRightNoDivider;
            }

            base.Render(graphicsContext, tab, index, area, cursor, tabLeftImage, tabCenterImage, tabRightImage);
        }
Example #10
0
        /// <summary>
        /// Gets the image to use for the right side of the tab.  For Chrome, we pick a specific image for inactive tabs that aren't at
        /// the end of the list to allow for the separation between inactive tabs to be more clearly defined.
        /// </summary>
        /// <param name="tab">Tab that we are retrieving the image for.</param>
        /// <returns>Right-side image for <paramref name="tab"/>.</returns>
        protected override Image GetTabRightImage(TitleBarTab tab)
        {
            ListWithEvents <TitleBarTab> allTabs = tab.Parent.Tabs;

            if (tab.Active || allTabs.IndexOf(tab) == allTabs.Count - 1)
            {
                return(base.GetTabRightImage(tab));
            }

            return(_inactiveRightSideShadowImage);
        }
Example #11
0
        /// <summary>Constructor; initializes the window and constructs the tab thumbnail image to use when dragging.</summary>
        /// <param name="tab">Tab that was torn out of its parent window.</param>
        /// <param name="tabRenderer">Renderer instance to use when drawing the actual tab.</param>
        public TornTabForm(TitleBarTab tab, BaseTabRenderer tabRenderer)
        {
            _layeredWindow = new LayeredWindow();
            _initialized   = false;

            // Set drawing styles
            SetStyle(ControlStyles.DoubleBuffer, true);

            // This should show up as a semi-transparent borderless window
            Opacity         = 0.70;
            ShowInTaskbar   = false;
            FormBorderStyle = FormBorderStyle.None;
// ReSharper disable DoNotCallOverridableMethodsInConstructor
            BackColor = Color.Fuchsia;
// ReSharper restore DoNotCallOverridableMethodsInConstructor
            TransparencyKey   = Color.Fuchsia;
            AllowTransparency = true;

            Disposed += TornTabForm_Disposed;

            // Get the tab thumbnail (full size) and then draw the actual representation of the tab onto it as well
            Bitmap   tabContents    = tab.GetImage();
            Bitmap   contentsAndTab = new Bitmap(tabContents.Width, tabContents.Height + tabRenderer.TabHeight, tabContents.PixelFormat);
            Graphics tabGraphics    = Graphics.FromImage(contentsAndTab);

            tabGraphics.DrawImage(tabContents, 0, tabRenderer.TabHeight);

            bool oldShowAddButton = tabRenderer.ShowAddButton;

            tabRenderer.ShowAddButton = false;
            tabRenderer.Render(
                new List <TitleBarTab>
            {
                tab
            }, tabGraphics, new Point(0, 0), new Point(0, 0), true);
            tabRenderer.ShowAddButton = oldShowAddButton;

            // Scale the thumbnail down to half size
            _tabThumbnail = new Bitmap(contentsAndTab.Width / 2, contentsAndTab.Height / 2, contentsAndTab.PixelFormat);
            Graphics thumbnailGraphics = Graphics.FromImage(_tabThumbnail);

            thumbnailGraphics.InterpolationMode  = InterpolationMode.High;
            thumbnailGraphics.CompositingQuality = CompositingQuality.HighQuality;
            thumbnailGraphics.SmoothingMode      = SmoothingMode.AntiAlias;
            thumbnailGraphics.DrawImage(contentsAndTab, 0, 0, _tabThumbnail.Width, _tabThumbnail.Height);

            Width  = _tabThumbnail.Width - 1;
            Height = _tabThumbnail.Height - 1;

            _cursorOffset = new Point(tabRenderer.TabContentWidth / 4, tabRenderer.TabHeight / 4);

            SetWindowPosition(Cursor.Position);
        }
Example #12
0
        /// <summary>Checks to see if the <paramref name="cursor" /> is over the <see cref="TitleBarTab.CloseButtonArea" /> of the given <paramref name="tab" />.</summary>
        /// <param name="tab">The tab whose <see cref="TitleBarTab.CloseButtonArea" /> we are to check to see if it contains <paramref name="cursor" />.</param>
        /// <param name="cursor">Current position of the cursor.</param>
        /// <returns>True if the <paramref name="tab" />'s <see cref="TitleBarTab.CloseButtonArea" /> contains <paramref name="cursor" />, false otherwise.</returns>
        public virtual bool IsOverCloseButton(TitleBarTab tab, Point cursor)
        {
            if (!tab.ShowCloseButton || _wasTabRepositioning)
            {
                return(false);
            }

            Rectangle absoluteCloseButtonArea = new Rectangle(
                tab.Area.X + tab.CloseButtonArea.X, tab.Area.Y + tab.CloseButtonArea.Y, tab.CloseButtonArea.Width, tab.CloseButtonArea.Height);

            return(absoluteCloseButtonArea.Contains(cursor));
        }
Example #13
0
        /// <summary>Resizes the <see cref="TitleBarTab.Content" /> form of the <paramref name="tab" /> to match the size of the client area for this window.</summary>
        /// <param name="tab">Tab whose <see cref="TitleBarTab.Content" /> form we should resize; if not specified, we default to
        /// <see cref="SelectedTab" />.</param>
        public void ResizeTabContents(TitleBarTab tab = null)
        {
            if (tab == null)
            {
                tab = SelectedTab;
            }

            if (tab != null)
            {
                tab.Content.Location = new Point(0, Padding.Top - 1);
                tab.Content.Size     = new Size(ClientRectangle.Width, ClientRectangle.Height - Padding.Top + 1);
            }
        }
Example #14
0
        /// <summary>
        /// Callback for the <see cref="TabSelected" /> event.  Called when a <see cref="TitleBarTab" /> gains focus.  Sets the active window in Aero Peek via a
        /// call to <see cref="TabbedThumbnailManager.SetActiveTab(Control)" />.
        /// </summary>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnTabSelected(TitleBarTabEventArgs e)
        {
            if (SelectedTabIndex != -1 && _previews.ContainsKey(SelectedTab.Content) && AeroPeekEnabled)
            {
                TaskbarManager.Instance.TabbedThumbnail.SetActiveTab(SelectedTab.Content);
            }

            _previousActiveTab = SelectedTab;

            if (TabSelected != null)
            {
                TabSelected(this, e);
            }
        }
Example #15
0
        /// <summary>
        /// Event handler that is called when a tab's <see cref="TitleBarTab.Closing" /> event is fired, which removes the tab from <see cref="Tabs" /> and
        /// re-renders <see cref="_overlay" />.
        /// </summary>
        /// <param name="sender">Object from which this event originated (the <see cref="TitleBarTab" /> in this case).</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void TitleBarTabs_Closing(object sender, CancelEventArgs e)
        {
            TitleBarTab tab = (TitleBarTab)sender;

            CloseTab(tab);

            if (!tab.Content.IsDisposed && AeroPeekEnabled)
            {
                TaskbarManager.Instance.TabbedThumbnail.RemoveThumbnailPreview(tab.Content);
            }

            if (_overlay != null)
            {
                _overlay.Render(true);
            }
        }
        private void StartTooltipTimer()
        {
            if (!_parentForm.ShowTooltips)
            {
                return;
            }

            Point       relativeCursorPosition = GetRelativeCursorPosition(Cursor.Position);
            TitleBarTab hoverTab = _parentForm.TabRenderer.OverTab(_parentForm.Tabs, relativeCursorPosition);

            if (hoverTab != null)
            {
                showTooltipTimer.Interval = hoverTab.Parent.Tooltip.AutomaticDelay;
                showTooltipTimer.Start();
            }
        }
Example #17
0
        public TornTabForm(TitleBarTab tab, BaseTabRenderer tabRenderer)
        {
            LayeredWindow = new LayeredWindow();
            Initialized   = false;
            SetStyle(ControlStyles.DoubleBuffer, true);
            Opacity           = 0.70;
            ShowInTaskbar     = false;
            FormBorderStyle   = FormBorderStyle.None;
            BackColor         = Color.Fuchsia;
            TransparencyKey   = Color.Fuchsia;
            AllowTransparency = true;

            Disposed += OnDisposed;

            Bitmap tabContents    = tab.GetThumbnail();
            Bitmap contentsAndTab = new Bitmap(tabContents.Width, tabContents.Height + tabRenderer.TabHeight,
                                               tabContents.PixelFormat);
            Graphics tabGraphics = Graphics.FromImage(contentsAndTab);

            tabGraphics.DrawImage(tabContents, 0, tabRenderer.TabHeight);

            bool oldShowAddButton = tabRenderer.ShowAddButton;

            tabRenderer.ShowAddButton = false;
            tabRenderer.Render(new List <TitleBarTab> {
                tab
            }, tabGraphics, new Point(0, 0), new Point(0, 0), true);
            tabRenderer.ShowAddButton = oldShowAddButton;

            TabThumbnail = new Bitmap(contentsAndTab.Width / 2, contentsAndTab.Height / 2, contentsAndTab.PixelFormat);
            Graphics thumbnailGraphics = Graphics.FromImage(TabThumbnail);

            thumbnailGraphics.InterpolationMode  = InterpolationMode.High;
            thumbnailGraphics.CompositingQuality = CompositingQuality.HighQuality;
            thumbnailGraphics.SmoothingMode      = SmoothingMode.AntiAlias;
            thumbnailGraphics.DrawImage(contentsAndTab, 0, 0, TabThumbnail.Width, TabThumbnail.Height);

            Width        = TabThumbnail.Width - 1;
            Height       = TabThumbnail.Height - 1;
            CursorOffset = new Point(tabRenderer.TabContentWidth / 4, tabRenderer.TabHeight / 4);
            SetWindowPosition(Cursor.Position);
        }
Example #18
0
        /// <summary>Generate a new thumbnail image for <paramref name="tab" />.</summary>
        /// <param name="tab">Tab that we need to generate a thumbnail for.</param>
        protected void UpdateTabThumbnail(TitleBarTab tab)
        {
            TabbedThumbnail preview = TaskbarManager.Instance.TabbedThumbnail.GetThumbnailPreview(tab.Content);

            if (preview == null)
            {
                return;
            }

            Bitmap bitmap = TabbedThumbnailScreenCapture.GrabWindowBitmap(tab.Content.Handle, tab.Content.Size);

            preview.SetImage(bitmap);

            // If we already had a preview image for the tab, dispose of it
            if (_previews.ContainsKey(tab.Content) && _previews[tab.Content] != null)
            {
                _previews[tab.Content].Dispose();
            }

            _previews[tab.Content] = bitmap;
        }
Example #19
0
        /// <summary>
        /// When a child tab updates its <see cref="Form.Icon"/> property, it should call this method to update the icon in the AeroPeek preview.
        /// </summary>
        /// <param name="tab">Tab whose icon was updated.</param>
        /// <param name="icon">The new icon to use.  If this is left as null, we use <see cref="Form.Icon"/> on <paramref name="tab"/>.</param>
        public virtual void UpdateThumbnailPreviewIcon(TitleBarTab tab, Icon icon = null)
        {
            if (!AeroPeekEnabled)
            {
                return;
            }

            TabbedThumbnail preview = TaskbarManager.Instance.TabbedThumbnail.GetThumbnailPreview(tab.Content);

            if (preview == null)
            {
                return;
            }

            if (icon == null)
            {
                icon = tab.Content.Icon;
            }

            preview.SetWindowIcon((Icon)icon.Clone());
        }
Example #20
0
        /// <summary>
        /// Called when a torn tab is dragged into the <see cref="TitleBarTabs.TabDropArea" /> of <see cref="_parentWindow" />.  Places the tab in the list and
        /// sets <see cref="IsTabRepositioning" /> to true to simulate the user continuing to drag the tab around in the window.
        /// </summary>
        /// <param name="tab">Tab that was dragged into this window.</param>
        /// <param name="cursorLocation">Location of the user's cursor.</param>
        internal virtual void CombineTab(TitleBarTab tab, Point cursorLocation)
        {
            // Stop rendering to prevent weird stuff from happening like the wrong tab being focused
            _suspendRendering = true;

            // Find out where to insert the tab in the list
            int dropIndex = _parentWindow.Tabs.FindIndex(t => t.Area.Left <= cursorLocation.X && t.Area.Right >= cursorLocation.X);

            // Simulate the user having clicked in the middle of the tab when they started dragging it so that the tab will move correctly within the window
            // when the user continues to move the mouse
            if (_parentWindow.Tabs.Count > 0)
            {
                _tabClickOffset = _parentWindow.Tabs.First().Area.Width / 2;
            }
            else
            {
                _tabClickOffset = 0;
            }
            IsTabRepositioning = true;

            tab.Parent = _parentWindow;

            if (dropIndex == -1)
            {
                _parentWindow.Tabs.Add(tab);
                dropIndex = _parentWindow.Tabs.Count - 1;
            }

            else
            {
                _parentWindow.Tabs.Insert(dropIndex, tab);
            }

            // Resume rendering
            _suspendRendering = false;

            _parentWindow.SelectedTabIndex = dropIndex;
            _parentWindow.ResizeTabContents();
        }
Example #21
0
        /// <summary>Calls <see cref="CreateTab" />, adds the resulting tab to the <see cref="Tabs" /> collection, and activates it.</summary>
        public virtual void AddNewTab()
        {
            TitleBarTab newTab = null;

            if (AutoCreateTab)
            {
                newTab = CreateTab();
                Tabs.Add(newTab);
                ResizeTabContents(newTab);
                SelectedTabIndex = _tabs.Count - 1;
            }

            var titleBarTabEventArgs = new TitleBarTabEventArgs
            {
                Tab         = newTab,
                TabIndex    = SelectedTabIndex,
                Action      = TabControlAction.Selected,
                WasDragging = false
            };

            TabCreated?.Invoke(this, titleBarTabEventArgs);
        }
Example #22
0
        /// <summary>Removes <paramref name="closingTab" /> from <see cref="Tabs" /> and selects the next applicable tab in the list.</summary>
        /// <param name="closingTab">Tab that is being closed.</param>
        protected virtual void CloseTab(TitleBarTab closingTab)
        {
            int removeIndex      = Tabs.IndexOf(closingTab);
            int selectedTabIndex = SelectedTabIndex;

            Tabs.Remove(closingTab);

            if (selectedTabIndex > removeIndex)
            {
                SelectedTabIndex = selectedTabIndex - 1;
            }

            else if (selectedTabIndex == removeIndex)
            {
                SelectedTabIndex = Math.Min(selectedTabIndex, Tabs.Count - 1);
            }

            else
            {
                SelectedTabIndex = selectedTabIndex;
            }

            if (_previews.ContainsKey(closingTab.Content))
            {
                _previews[closingTab.Content].Dispose();
                _previews.Remove(closingTab.Content);
            }

            if (_previousActiveTab != null && closingTab.Content == _previousActiveTab.Content)
            {
                _previousActiveTab = null;
            }

            if (Tabs.Count == 0 && ExitOnLastTabClose)
            {
                Close();
            }
        }
Example #23
0
        /// <summary>
        /// Called from the <see cref="_parentWindow" /> to determine which, if any, of the <paramref name="tabs" /> the <paramref name="cursor" /> is
        /// over.
        /// </summary>
        /// <param name="tabs">The list of tabs that we should check.</param>
        /// <param name="cursor">The relative position of the cursor within the window.</param>
        /// <returns>The tab within <paramref name="tabs" /> that the <paramref name="cursor" /> is over; if none, then null is returned.</returns>
        public virtual TitleBarTab OverTab(IEnumerable <TitleBarTab> tabs, Point cursor)
        {
            TitleBarTab overTab = null;

            foreach (TitleBarTab tab in tabs.Where(tab => tab.TabImage != null))
            {
                // We have to loop through each of the tabs in turn and check their status; if the tabs overlap, then their areas overlap as well, which means
                // that we may find see that the cursor is over an inactive tab, but we need to check the active tabs as well, since they may overlap their
                // areas and take precedence.
                if (tab.Active && IsOverTab(tab, cursor))
                {
                    overTab = tab;
                    break;
                }

                if (IsOverTab(tab, cursor))
                {
                    overTab = tab;
                }
            }

            return(overTab);
        }
        /// <summary>Overrides the message pump for the window so that we can respond to click events on the tabs themselves.</summary>
        /// <param name="m">Message received by the pump.</param>
        protected override void WndProc(ref Message m)
        {
            switch ((WM)m.Msg)
            {
            case WM.WM_NCLBUTTONDOWN:
            case WM.WM_LBUTTONDOWN:
                Point relativeCursorPosition = GetRelativeCursorPosition(Cursor.Position);

                // If we were over a tab, set the capture state for the window so that we'll actually receive a WM_LBUTTONUP message
                if (_parentForm.TabRenderer.OverTab(_parentForm.Tabs, relativeCursorPosition) == null &&
                    !_parentForm.TabRenderer.IsOverAddButton(relativeCursorPosition))
                {
                    _parentForm.ForwardMessage(ref m);
                }

                else
                {
                    // When the user clicks a mouse button, save the tab that the user was over so we can respond properly when the mouse button is released
                    TitleBarTab clickedTab = _parentForm.TabRenderer.OverTab(_parentForm.Tabs, relativeCursorPosition);

                    if (clickedTab != null)
                    {
                        // If the user clicked the close button, remove the tab from the list
                        if (!_parentForm.TabRenderer.IsOverCloseButton(clickedTab, relativeCursorPosition))
                        {
                            _parentForm.ResizeTabContents(clickedTab);
                            _parentForm.SelectedTabIndex = _parentForm.Tabs.IndexOf(clickedTab);

                            Render();
                        }

                        OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0));
                    }

                    _parentForm.Activate();
                }

                break;

            case WM.WM_LBUTTONDBLCLK:
                _parentForm.ForwardMessage(ref m);
                break;

            // We always return HTCAPTION for the hit test message so that the underlying window doesn't have its focus removed
            case WM.WM_NCHITTEST:
                m.Result = new IntPtr((int)HT.HTCAPTION);
                break;

            case WM.WM_LBUTTONUP:
            case WM.WM_NCLBUTTONUP:
            case WM.WM_MBUTTONUP:
            case WM.WM_NCMBUTTONUP:
                Point relativeCursorPosition2 = GetRelativeCursorPosition(Cursor.Position);

                if (_parentForm.TabRenderer.OverTab(_parentForm.Tabs, relativeCursorPosition2) == null &&
                    !_parentForm.TabRenderer.IsOverAddButton(relativeCursorPosition2))
                {
                    _parentForm.ForwardMessage(ref m);
                }

                else
                {
                    // When the user clicks a mouse button, save the tab that the user was over so we can respond properly when the mouse button is released
                    TitleBarTab clickedTab = _parentForm.TabRenderer.OverTab(_parentForm.Tabs, relativeCursorPosition2);

                    if (clickedTab != null)
                    {
                        // If the user clicks the middle button/scroll wheel over a tab, close it
                        if ((WM)m.Msg == WM.WM_MBUTTONUP || (WM)m.Msg == WM.WM_NCMBUTTONUP)
                        {
                            clickedTab.Content.Close();
                            Render();
                        }

                        else
                        {
                            // If the user clicked the close button, remove the tab from the list
                            if (_parentForm.TabRenderer.IsOverCloseButton(clickedTab, relativeCursorPosition2))
                            {
                                clickedTab.Content.Close();
                                Render();
                            }

                            else
                            {
                                _parentForm.OnTabClicked(
                                    new TitleBarTabEventArgs
                                {
                                    Tab         = clickedTab,
                                    TabIndex    = _parentForm.SelectedTabIndex,
                                    Action      = TabControlAction.Selected,
                                    WasDragging = _wasDragging
                                });
                            }
                        }
                    }

                    // Otherwise, if the user clicked the add button, call CreateTab to add a new tab to the list and select it
                    else if (_parentForm.TabRenderer.IsOverAddButton(relativeCursorPosition2))
                    {
                        _parentForm.AddNewTab();
                    }

                    if ((WM)m.Msg == WM.WM_LBUTTONUP || (WM)m.Msg == WM.WM_NCLBUTTONUP)
                    {
                        OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0));
                    }
                }

                break;

            default:
                base.WndProc(ref m);
                break;
            }
        }
Example #25
0
 public TitleBarTabCancelEventArgs(TabControlAction action, TitleBarTab tab, int tabIndex)
 {
     Action   = action;
     Tab      = tab;
     TabIndex = tabIndex;
 }
Example #26
0
        /// <summary>
        /// Creates a new tab to hold <paramref name="form"/>.
        /// </summary>
        /// <param name="form">Form instance that we are to open in a new tab.</param>
        protected void ShowInEmptyTab(Form form)
        {
            // If we're opening the form from an unconnected ConnectionWindow, just replace its content with the new form
            if (SelectedTab != null && SelectedTab.Content is ConnectionWindow && !(SelectedTab.Content as ConnectionWindow).IsConnected)
            {
                Form oldWindow = SelectedTab.Content;

                SelectedTab.Content = form;
                ResizeTabContents();

                oldWindow.Close();
            }

                // Otherwise, create a new tab associated with the form
            else
            {
                TitleBarTab newTab = new TitleBarTab(this)
                                         {
                                             Content = form
                                         };

                Tabs.Add(newTab);
                ResizeTabContents(newTab);
                SelectedTabIndex = _tabs.Count - 1;
            }

            form.Show();

            if (_overlay != null)
                _overlay.Render(true);
        }
Example #27
0
        /// <summary>Internal method for rendering an individual <paramref name="tab" /> to the screen.</summary>
        /// <param name="graphicsContext">Graphics context to use when rendering the tab.</param>
        /// <param name="tab">Individual tab that we are to render.</param>
        /// <param name="area">Area of the screen that the tab should be rendered to.</param>
        /// <param name="cursor">Current position of the cursor.</param>
        /// <param name="tabLeftImage">Image to use for the left side of the tab.</param>
        /// <param name="tabCenterImage">Image to use for the center of the tab.</param>
        /// <param name="tabRightImage">Image to use for the right side of the tab.</param>
        protected virtual void Render(Graphics graphicsContext, TitleBarTab tab, Rectangle area, Point cursor, Image tabLeftImage, Image tabCenterImage, Image tabRightImage)
        {
            if (_suspendRendering)
            {
                return;
            }

            // If we need to redraw the tab image
            if (tab.TabImage == null)
            {
                // We render the tab to an internal property so that we don't necessarily have to redraw it in every rendering pass, only if its width or
                // status have changed
                tab.TabImage = new Bitmap(area.Width <= 0 ? 1 : area.Width, tabCenterImage.Height <= 0 ? 1 : tabCenterImage.Height);

                using (Graphics tabGraphicsContext = Graphics.FromImage(tab.TabImage))
                {
                    // Draw the left, center, and right portions of the tab
                    tabGraphicsContext.DrawImage(
                        tabLeftImage, new Rectangle(0, 0, tabLeftImage.Width, tabLeftImage.Height), 0, 0, tabLeftImage.Width, tabLeftImage.Height, GraphicsUnit.Pixel);

                    tabGraphicsContext.DrawImage(
                        tabCenterImage, new Rectangle(tabLeftImage.Width, 0, _tabContentWidth, tabCenterImage.Height), 0, 0, _tabContentWidth, tabCenterImage.Height,
                        GraphicsUnit.Pixel);

                    tabGraphicsContext.DrawImage(
                        tabRightImage, new Rectangle(tabLeftImage.Width + _tabContentWidth, 0, tabRightImage.Width, tabRightImage.Height), 0, 0, tabRightImage.Width,
                        tabRightImage.Height, GraphicsUnit.Pixel);

                    // Draw the close button
                    if (tab.ShowCloseButton)
                    {
                        Image closeButtonImage = IsOverCloseButton(tab, cursor)
                                                        ? _closeButtonHoverImage
                                                        : _closeButtonImage;

                        tab.CloseButtonArea = new Rectangle(
                            area.Width - tabRightImage.Width - CloseButtonMarginRight - closeButtonImage.Width, CloseButtonMarginTop, closeButtonImage.Width,
                            closeButtonImage.Height);

                        tabGraphicsContext.DrawImage(
                            closeButtonImage, tab.CloseButtonArea, 0, 0,
                            closeButtonImage.Width, closeButtonImage.Height,
                            GraphicsUnit.Pixel);
                    }
                }

                tab.Area = area;
            }

            // Render the tab's saved image to the screen
            graphicsContext.DrawImage(
                tab.TabImage, area, 0, 0, tab.TabImage.Width, tab.TabImage.Height,
                GraphicsUnit.Pixel);

            // Render the icon for the tab's content, if it exists and there's room for it in the tab's content area
            if (tab.Content.ShowIcon && _tabContentWidth > 16 + IconMarginLeft + (tab.ShowCloseButton
                                ? CloseButtonMarginLeft +
                                                                                  tab.CloseButtonArea.Width +
                                                                                  CloseButtonMarginRight
                                : 0))
            {
                graphicsContext.DrawIcon(
                    new Icon(tab.Content.Icon, 16, 16),
                    new Rectangle(area.X + OverlapWidth + IconMarginLeft, IconMarginTop + area.Y, 16, 16));
            }

            // Render the caption for the tab's content if there's room for it in the tab's content area
            if (_tabContentWidth > (tab.Content.ShowIcon
                                ? 16 + IconMarginLeft + IconMarginRight
                                : 0) + CaptionMarginLeft + CaptionMarginRight + (tab.ShowCloseButton
                                        ? CloseButtonMarginLeft +
                                                                                 tab.CloseButtonArea.Width +
                                                                                 CloseButtonMarginRight
                                        : 0))
            {
                graphicsContext.DrawString(
                    tab.Caption, CaptionFont, new SolidBrush(ForeColor),
                    new Rectangle(
                        area.X + OverlapWidth + CaptionMarginLeft + (tab.Content.ShowIcon
                                                        ? IconMarginLeft +
                                                                     16 +
                                                                     IconMarginRight
                                                        : 0),
                        CaptionMarginTop + area.Y,
                        _tabContentWidth - (tab.Content.ShowIcon
                                                        ? IconMarginLeft + 16 + IconMarginRight
                                                        : 0) - (tab.ShowCloseButton
                                                                ? _closeButtonImage.Width +
                                                                CloseButtonMarginRight +
                                                                CloseButtonMarginLeft
                                                                : 0), tab.TabImage.Height),
                    new StringFormat(StringFormatFlags.NoWrap)
                {
                    Trimming = StringTrimming.EllipsisCharacter
                });
            }
        }
Example #28
0
        /// <summary>
        /// Handler method that's called when the user clicks the "Edit" menu item in the context menu that appears when the user right-clicks on a bookmark
        /// in the list view.  Opens the options window for the connection's protocol type.
        /// </summary>
        /// <param name="sender">Object from which this event originated.</param>
        /// <param name="e">Arguments associated with this event.</param>
        private void _editBookmarkMenuItem_Click(object sender, EventArgs e)
        {
            ListViewItem selectedItem = _bookmarksListView.SelectedItems[0];
            TitleBarTab optionsTab = new TitleBarTab(ParentTabs)
                                         {
                                             Content = new OptionsWindow(ParentTabs)
                                                           {
                                                               OptionsForms = new List<Form>
                                                                                  {
                                                                                      ConnectionFactory.CreateOptionsForm(_listViewConnections[selectedItem])
                                                                                  },
                                                               Text = "Options for " + _listViewConnections[selectedItem].DisplayName
                                                           }
                                         };

            // When the options form is closed, update the second column in the list view with the updated host for the connection
            optionsTab.Content.FormClosed += (o, args) => selectedItem.SubItems[1].Text = _listViewConnections[selectedItem].Host;

            ParentTabs.Tabs.Add(optionsTab);
            ParentTabs.ResizeTabContents(optionsTab);
            ParentTabs.SelectedTab = optionsTab;
        }
Example #29
0
        /// <summary>
        /// Opens a new tab for <paramref name="connection"/>.
        /// </summary>
        /// <param name="connection">Connection that we are to open a new tab for.</param>
        /// <param name="focusNewTab">Flag indicating whether we should focus on the new tab.</param>
        /// <returns>Tab that was created for <paramref name="connection"/>.</returns>
        public TitleBarTab Connect(IConnection connection, bool focusNewTab)
        {
            ConnectionWindow connectionWindow = new ConnectionWindow(connection);

            TitleBarTab newTab = new TitleBarTab(this)
                                     {
                                         Content = connectionWindow
                                     };
            Tabs.Insert(SelectedTabIndex + 1, newTab);
            ResizeTabContents(newTab);

            if (focusNewTab)
            {
                SelectedTab = newTab;
                _previouslyClickedTab = newTab;
            }

            connectionWindow.Connect();

            return newTab;
        }
Example #30
0
        /// <summary>
        /// Handler method that's called when the user clicks on the "Properties..." menu item in the context menu that appears when the user right-clicks on
        /// a history entry; opens up the options for the connection in a new tab.
        /// </summary>
        /// <param name="sender">Object from which this event originated.</param>
        /// <param name="e">Argument associated with this event.</param>
        private void propertiesMenuItem_Click(object sender, EventArgs e)
        {
            // Get the options form for the connection type and open it in a new tab
            Form optionsWindow = ConnectionFactory.CreateOptionsForm(_connections[_historyListView.SelectedItems[0]].Connection);
            TitleBarTab optionsTab = new TitleBarTab(_applicationForm)
                                         {
                                             Content = optionsWindow
                                         };

            _applicationForm.Tabs.Add(optionsTab);
            _applicationForm.SelectedTab = optionsTab;
        }
Example #31
0
        /// <summary>
        /// Handler method that's called when a tab is clicked on.  This is different from the <see cref="TitleBarTabs.TabSelected"/> event handler in that 
        /// this is called even if the tab is currently active.  This is used to show the toolbar for <see cref="ConnectionWindow"/> instances that 
        /// automatically hide their toolbars when the connection's UI is focused on.
        /// </summary>
        /// <param name="sender">Object from which this event originated.</param>
        /// <param name="e">Arguments associated with this event.</param>
        private void MainForm_TabClicked(object sender, TitleBarTabEventArgs e)
        {
            // Only show the toolbar if the user clicked on an already-selected tab
            if (e.Tab.Content is ConnectionWindow && e.Tab == _previouslyClickedTab && !e.WasDragging)
                (e.Tab.Content as ConnectionWindow).ShowToolbar();

            _previouslyClickedTab = e.Tab;
        }
Example #32
0
 /// <summary>
 /// Gets the image to use for the center of the <paramref name="tab"/>.
 /// </summary>
 /// <param name="tab">Tab that we are retrieving the image for.</param>
 /// <returns>The image for the center of <paramref name="tab"/>.</returns>
 protected virtual Image GetTabCenterImage(TitleBarTab tab)
 {
     return(tab.Active
                         ? _activeCenterImage
                         : _inactiveCenterImage);
 }
Example #33
0
        /// <summary>
        /// Consumer method that processes mouse events in <see cref="MouseEvents" /> that are recorded by <see cref="MouseHookCallback" />
        /// </summary>
        protected void InterpretMouseEvents()
        {
            foreach (MouseEvent mouseEvent in MouseEvents.GetConsumingEnumerable())
            {
                int            nCode      = mouseEvent.nCode;
                IntPtr         wParam     = mouseEvent.wParam;
                MSLLHOOKSTRUCT?hookStruct = mouseEvent.MouseData;
                if (nCode >= 0 && (int)WM.WM_MOUSEMOVE == (int)wParam)
                {
                    Point cursorPosition = new Point(hookStruct.Value.pt.x, hookStruct.Value.pt.y);
                    bool  reRender       = false;
                    if (s_tornTab != null && DropAreas != null)
                    {
                        for (int i = 0; i < DropAreas.Length; i++)
                        {
                            if (DropAreas[i].Item2.Contains(cursorPosition)) // If the cursor is within the drop area, combine the tab for the window that belongs to that drop area
                            {
                                TitleBarTab tabToCombine = null;
                                lock (s_tornTabLock)
                                {
                                    if (s_tornTab != null)
                                    {
                                        tabToCombine = s_tornTab;
                                        s_tornTab    = null;
                                    }
                                }

                                if (tabToCombine != null)
                                {
                                    int i1 = i;
                                    Invoke(new Action(() =>
                                    {
                                        DropAreas[i1].Item1.TabRenderer.CombineTab(tabToCombine, cursorPosition);
                                        tabToCombine = null;
                                        s_tornTabForm.Close();
                                        s_tornTabForm = null;
                                        if (ParentForm.Tabs.Count == 0)
                                        {
                                            ParentForm.Close();
                                        }
                                    }));
                                }
                            }
                        }
                    }
                    else if (!ParentForm.TabRenderer.IsTabRepositioning)
                    {
                        // If we were over a close button previously, check to see if the cursor is still over that tab's close button; if not, re-render
                        if (IsOverCLoseButtonForTab != -1 && (IsOverCLoseButtonForTab >= ParentForm.Tabs.Count || !ParentForm.TabRenderer.IsOverCloseButton(ParentForm.Tabs[IsOverCLoseButtonForTab], GetRelativeCursorPosition(cursorPosition))))
                        {
                            reRender = true;
                            IsOverCLoseButtonForTab = -1;
                        }
                        else // Otherwise, see if any tabs' close button is being hovered over
                        {
                            for (int i = 0; i < ParentForm.Tabs.Count; i++)
                            {
                                if (ParentForm.TabRenderer.IsOverCloseButton(ParentForm.Tabs[i], GetRelativeCursorPosition(cursorPosition)))
                                {
                                    IsOverCLoseButtonForTab = i;
                                    reRender = true;
                                    break;
                                }
                            }
                        }
                    }
                    else
                    {
                        Invoke(new Action(() =>
                        {
                            s_wasDragging      = true;
                            Rectangle dragArea = TabDropArea;
                            dragArea.Inflate(ParentForm.TabRenderer.TabTearDragDistance, ParentForm.TabRenderer.TabTearDragDistance);
                            if (!dragArea.Contains(cursorPosition) && s_tornTab == null)
                            {
                                lock (s_tornTabLock)
                                {
                                    if (s_tornTab == null)
                                    {
                                        ParentForm.TabRenderer.IsTabRepositioning = false;
                                        s_tornTab = ParentForm.SelectedTab;
                                        s_tornTab.ClearEventSubscriptions();
                                        s_tornTabForm = new TornTabForm(s_tornTab, ParentForm.TabRenderer);
                                    }
                                }

                                if (s_tornTab != null)
                                {
                                    ParentForm.SelectedTabIndex = ParentForm.SelectedTabIndex == ParentForm.Tabs.Count - 1 ? ParentForm.SelectedTabIndex - 1 : ParentForm.SelectedTabIndex + 1;
                                    ParentForm.Tabs.Remove(s_tornTab);
                                    if (ParentForm.Tabs.Count == 0)
                                    {
                                        ParentForm.Hide();
                                    }
                                    s_tornTabForm.Show();
                                    DropAreas = (from window in ParentForm.ApplicationContext.OpenWindows.Where(w => w.Tabs.Count > 0) select new Tuple <TitleBarTabs, Rectangle>(window, window.TabDropArea)).ToArray();
                                }
                            }
                        }));
                    }
                    Invoke(new Action(() => OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, cursorPosition.X, cursorPosition.Y, 0))));
                    if (ParentForm.TabRenderer.IsTabRepositioning)
                    {
                        reRender = true;
                    }
                    if (reRender)
                    {
                        Invoke(new Action(() => Render(cursorPosition, true)));
                    }
                }
                else if (nCode >= 0 && (int)WM.WM_LBUTTONDOWN == (int)wParam)
                {
                    s_wasDragging = false;
                }
                else if (nCode >= 0 && (int)WM.WM_LBUTTONUP == (int)wParam)
                {
                    if (s_tornTab != null)
                    {
                        TitleBarTab tabToRelease = null;
                        lock (s_tornTabLock)
                        {
                            if (s_tornTab != null)
                            {
                                tabToRelease = s_tornTab;
                                s_tornTab    = null;
                            }
                        }

                        if (tabToRelease != null)
                        {
                            Invoke(new Action(() =>
                            {
                                TitleBarTabs newWindow = (TitleBarTabs)Activator.CreateInstance(ParentForm.GetType());
                                if (newWindow.WindowState == FormWindowState.Maximized)
                                {
                                    Screen screen           = Screen.AllScreens.First(s => s.WorkingArea.Contains(Cursor.Position));
                                    newWindow.StartPosition = FormStartPosition.Manual;
                                    newWindow.WindowState   = FormWindowState.Normal;
                                    newWindow.Left          = screen.WorkingArea.Left;
                                    newWindow.Top           = screen.WorkingArea.Top;
                                    newWindow.Width         = screen.WorkingArea.Width;
                                    newWindow.Height        = screen.WorkingArea.Height;
                                }
                                else
                                {
                                    newWindow.Left = Cursor.Position.X;
                                    newWindow.Top  = Cursor.Position.Y;
                                }
                                tabToRelease.Parent = newWindow;
                                ParentForm.ApplicationContext.OpenWindow(newWindow);
                                newWindow.Show();
                                newWindow.Tabs.Add(tabToRelease);
                                newWindow.SelectedTabIndex = 0;
                                newWindow.ResizeTabContents();
                                s_tornTabForm.Close();
                                s_tornTabForm = null;
                                if (ParentForm.Tabs.Count == 0)
                                {
                                    ParentForm.Close();
                                }
                            }));
                        }
                    }
                    Invoke(new Action(() => OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0))));
                }
            }
        }
        /// <summary>Consumer method that processes mouse events in <see cref="_mouseEvents" /> that are recorded by <see cref="MouseHookCallback" />.</summary>
        protected void InterpretMouseEvents()
        {
            foreach (MouseEvent mouseEvent in _mouseEvents.GetConsumingEnumerable())
            {
                int            nCode      = mouseEvent.nCode;
                IntPtr         wParam     = mouseEvent.wParam;
                MSLLHOOKSTRUCT?hookStruct = mouseEvent.MouseData;

                if (nCode >= 0 && (int)WM.WM_MOUSEMOVE == (int)wParam)
                {
                    HideTooltip();

                    // ReSharper disable PossibleInvalidOperationException
                    Point cursorPosition = new Point(hookStruct.Value.pt.x, hookStruct.Value.pt.y);
                    // ReSharper restore PossibleInvalidOperationException
                    bool reRender = false;

                    if (_tornTab != null && _dropAreas != null)
                    {
                        // ReSharper disable ForCanBeConvertedToForeach
                        for (int i = 0; i < _dropAreas.Length; i++)
                        // ReSharper restore ForCanBeConvertedToForeach
                        {
                            // If the cursor is within the drop area, combine the tab for the window that belongs to that drop area
                            if (_dropAreas[i].Item2.Contains(cursorPosition))
                            {
                                TitleBarTab tabToCombine = null;

                                lock (_tornTabLock)
                                {
                                    if (_tornTab != null)
                                    {
                                        tabToCombine = _tornTab;
                                        _tornTab     = null;
                                    }
                                }

                                if (tabToCombine != null)
                                {
                                    int i1 = i;

                                    // In all cases where we need to affect the UI, we call Invoke so that those changes are made on the main UI thread since
                                    // we are on a separate processing thread in this case
                                    Invoke(
                                        new Action(
                                            () =>
                                    {
                                        _dropAreas[i1].Item1.TabRenderer.CombineTab(tabToCombine, cursorPosition);

                                        tabToCombine = null;
                                        _tornTabForm.Close();
                                        _tornTabForm = null;

                                        if (_parentForm.Tabs.Count == 0)
                                        {
                                            _parentForm.Close();
                                        }
                                    }));
                                }
                            }
                        }
                    }

                    else if (!_parentForm.TabRenderer.IsTabRepositioning)
                    {
                        StartTooltipTimer();

                        // If we were over a close button previously, check to see if the cursor is still over that tab's
                        // close button; if not, re-render
                        if (_isOverCloseButtonForTab != -1 &&
                            (_isOverCloseButtonForTab >= _parentForm.Tabs.Count ||
                             !_parentForm.TabRenderer.IsOverCloseButton(_parentForm.Tabs[_isOverCloseButtonForTab], GetRelativeCursorPosition(cursorPosition))))
                        {
                            reRender = true;
                            _isOverCloseButtonForTab = -1;
                        }

                        // Otherwise, see if any tabs' close button is being hovered over
                        else
                        {
                            // ReSharper disable ForCanBeConvertedToForeach
                            for (int i = 0; i < _parentForm.Tabs.Count; i++)
                            // ReSharper restore ForCanBeConvertedToForeach
                            {
                                if (_parentForm.TabRenderer.IsOverCloseButton(_parentForm.Tabs[i], GetRelativeCursorPosition(cursorPosition)))
                                {
                                    _isOverCloseButtonForTab = i;
                                    reRender = true;

                                    break;
                                }
                            }
                        }
                    }

                    else
                    {
                        Invoke(
                            new Action(
                                () =>
                        {
                            _wasDragging = true;

                            // When determining if a tab has been torn from the window while dragging, we take the drop area for this window and inflate it by the
                            // TabTearDragDistance setting
                            Rectangle dragArea = TabDropArea;
                            dragArea.Inflate(_parentForm.TabRenderer.TabTearDragDistance, _parentForm.TabRenderer.TabTearDragDistance);

                            // If the cursor is outside the tear area, tear it away from the current window
                            if (!dragArea.Contains(cursorPosition) && _tornTab == null)
                            {
                                lock (_tornTabLock)
                                {
                                    if (_tornTab == null)
                                    {
                                        _parentForm.TabRenderer.IsTabRepositioning = false;

                                        // Clear the event handler subscriptions from the tab and then create a thumbnail representation of it to use when dragging
                                        _tornTab = _parentForm.SelectedTab;
                                        _tornTab.ClearSubscriptions();
                                        _tornTabForm = new TornTabForm(_tornTab, _parentForm.TabRenderer);
                                    }
                                }

                                if (_tornTab != null)
                                {
                                    _parentForm.SelectedTabIndex = (_parentForm.SelectedTabIndex == _parentForm.Tabs.Count - 1
                                                                                                ? _parentForm.SelectedTabIndex - 1
                                                                                                : _parentForm.SelectedTabIndex + 1);
                                    _parentForm.Tabs.Remove(_tornTab);

                                    // If this tab was the only tab in the window, hide the parent window
                                    if (_parentForm.Tabs.Count == 0)
                                    {
                                        _parentForm.Hide();
                                    }

                                    _tornTabForm.Show();
                                    _dropAreas = (from window in _parentForm.ApplicationContext.OpenWindows.Where(w => w.Tabs.Count > 0)
                                                  select new Tuple <TitleBarTabs, Rectangle>(window, window.TabDropArea)).ToArray();
                                }
                            }
                        }));
                    }

                    Invoke(new Action(() => OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, cursorPosition.X, cursorPosition.Y, 0))));

                    if (_parentForm.TabRenderer.IsTabRepositioning)
                    {
                        reRender = true;
                    }

                    if (reRender)
                    {
                        Invoke(new Action(() => Render(cursorPosition, true)));
                    }
                }

                else if (nCode >= 0 && (int)WM.WM_LBUTTONDOWN == (int)wParam)
                {
                    _wasDragging = false;
                }

                else if (nCode >= 0 && (int)WM.WM_LBUTTONUP == (int)wParam)
                {
                    // If we released the mouse button while we were dragging a torn tab, put that tab into a new window
                    if (_tornTab != null)
                    {
                        TitleBarTab tabToRelease = null;

                        lock (_tornTabLock)
                        {
                            if (_tornTab != null)
                            {
                                tabToRelease = _tornTab;
                                _tornTab     = null;
                            }
                        }

                        if (tabToRelease != null)
                        {
                            Invoke(
                                new Action(
                                    () =>
                            {
                                TitleBarTabs newWindow = (TitleBarTabs)Activator.CreateInstance(_parentForm.GetType());

                                // Set the initial window position and state properly
                                if (newWindow.WindowState == FormWindowState.Maximized)
                                {
                                    Screen screen = Screen.AllScreens.First(s => s.WorkingArea.Contains(Cursor.Position));

                                    newWindow.StartPosition = FormStartPosition.Manual;
                                    newWindow.WindowState   = FormWindowState.Normal;
                                    newWindow.Left          = screen.WorkingArea.Left;
                                    newWindow.Top           = screen.WorkingArea.Top;
                                    newWindow.Width         = screen.WorkingArea.Width;
                                    newWindow.Height        = screen.WorkingArea.Height;
                                }

                                else
                                {
                                    newWindow.Left = Cursor.Position.X;
                                    newWindow.Top  = Cursor.Position.Y;
                                }

                                tabToRelease.Parent = newWindow;
                                _parentForm.ApplicationContext.OpenWindow(newWindow);

                                newWindow.Show();
                                newWindow.Tabs.Add(tabToRelease);
                                newWindow.SelectedTabIndex = 0;
                                newWindow.ResizeTabContents();

                                _tornTabForm.Close();
                                _tornTabForm = null;

                                if (_parentForm.Tabs.Count == 0)
                                {
                                    _parentForm.Close();
                                }
                            }));
                        }
                    }

                    Invoke(new Action(() => OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0))));
                }
            }
        }
Example #35
0
        /// <summary>Renders the list of <paramref name="tabs" /> to the screen using the given <paramref name="graphicsContext" />.</summary>
        /// <param name="tabs">List of tabs that we are to render.</param>
        /// <param name="graphicsContext">Graphics context that we should use while rendering.</param>
        /// <param name="cursor">Current location of the cursor on the screen.</param>
        /// <param name="forceRedraw">Flag indicating whether or not the redraw should be forced.</param>
        /// <param name="offset">Offset within <paramref name="graphicsContext" /> that the tabs should be rendered.</param>
        public virtual void Render(List <TitleBarTab> tabs, Graphics graphicsContext, Point offset, Point cursor, bool forceRedraw = false)
        {
            if (_suspendRendering)
            {
                return;
            }

            if (tabs == null || tabs.Count == 0)
            {
                return;
            }

            Point screenCoordinates = _parentWindow.PointToScreen(_parentWindow.ClientRectangle.Location);

            // Calculate the maximum tab area, excluding the add button and any minimize/maximize/close buttons in the window
            _maxTabArea.Location = new Point(SystemInformation.BorderSize.Width + offset.X + screenCoordinates.X, offset.Y + screenCoordinates.Y);
            _maxTabArea.Width    = GetMaxTabAreaWidth(tabs, offset);
            _maxTabArea.Height   = TabHeight;

            // Get the width of the content area for each tab by taking the parent window's client width, subtracting the left and right border widths and the
            // add button area (if applicable) and then dividing by the number of tabs
            int tabContentWidth = Math.Min(_activeCenterImage.Width, Convert.ToInt32(Math.Floor(Convert.ToDouble(_maxTabArea.Width / tabs.Count))));

            // Determine if we need to redraw the TabImage properties for each tab by seeing if the content width that we calculated above is equal to content
            // width we had in the previous rendering pass
            bool redraw = tabContentWidth != _tabContentWidth || forceRedraw;

            if (redraw)
            {
                _tabContentWidth = tabContentWidth;
            }

            int i = tabs.Count - 1;
            List <Tuple <TitleBarTab, Rectangle> > activeTabs = new List <Tuple <TitleBarTab, Rectangle> >();

            // Render the background image
            if (_background != null)
            {
                graphicsContext.DrawImage(_background, offset.X, offset.Y, _parentWindow.Width, TabHeight);
            }

            int   selectedIndex  = tabs.FindIndex(t => t.Active);
            Image tabCenterImage = null;

            if (selectedIndex != -1)
            {
                TitleBarTab selectedTab = tabs[selectedIndex];

                Image tabLeftImage  = GetTabLeftImage(selectedTab);
                Image tabRightImage = GetTabRightImage(selectedTab);
                tabCenterImage = GetTabCenterImage(selectedTab);

                Rectangle tabArea = new Rectangle(
                    SystemInformation.BorderSize.Width + offset.X +
                    selectedIndex * (tabContentWidth + tabLeftImage.Width + tabRightImage.Width - OverlapWidth),
                    offset.Y + (TabHeight - tabCenterImage.Height), tabContentWidth + tabLeftImage.Width + tabRightImage.Width,
                    tabCenterImage.Height);

                if (IsTabRepositioning && _tabClickOffset != null)
                {
                    // Make sure that the user doesn't move the tab past the beginning of the list or the outside of the window
                    tabArea.X = cursor.X - _tabClickOffset.Value;
                    tabArea.X = Math.Max(SystemInformation.BorderSize.Width + offset.X, tabArea.X);
                    tabArea.X =
                        Math.Min(
                            SystemInformation.BorderSize.Width + (_parentWindow.WindowState == FormWindowState.Maximized
                                                                ? _parentWindow.ClientRectangle.Width - (_parentWindow.ControlBox
                                                                        ? SystemInformation.CaptionButtonSize.Width
                                                                        : 0) -
                                                                  (_parentWindow.MinimizeBox
                                                                          ? SystemInformation.CaptionButtonSize.Width
                                                                          : 0) -
                                                                  (_parentWindow.MaximizeBox
                                                                          ? SystemInformation.CaptionButtonSize.Width
                                                                          : 0)
                                                                : _parentWindow.ClientRectangle.Width) - tabArea.Width, tabArea.X);

                    int dropIndex = 0;

                    // Figure out which slot the active tab is being "dropped" over
                    if (tabArea.X - SystemInformation.BorderSize.Width - offset.X - TabRepositionDragDistance > 0)
                    {
                        dropIndex =
                            Math.Min(
                                Convert.ToInt32(
                                    Math.Round(
                                        Convert.ToDouble(tabArea.X - SystemInformation.BorderSize.Width - offset.X - TabRepositionDragDistance) /
                                        Convert.ToDouble(tabArea.Width - OverlapWidth))), tabs.Count - 1);
                    }

                    // If the tab has been moved over another slot, move the tab object in the window's tab list
                    if (dropIndex != selectedIndex)
                    {
                        TitleBarTab tab = tabs[selectedIndex];

                        _parentWindow.Tabs.SuppressEvents();
                        _parentWindow.Tabs.Remove(tab);
                        _parentWindow.Tabs.Insert(dropIndex, tab);
                        _parentWindow.Tabs.ResumeEvents();
                    }
                }

                activeTabs.Add(new Tuple <TitleBarTab, Rectangle>(tabs[selectedIndex], tabArea));
            }

            // Loop through the tabs in reverse order since we need the ones farthest on the left to overlap those to their right
            foreach (TitleBarTab tab in ((IEnumerable <TitleBarTab>)tabs).Reverse())
            {
                Image tabLeftImage = GetTabLeftImage(tab);
                tabCenterImage = GetTabCenterImage(tab);
                Image tabRightImage = GetTabRightImage(tab);

                Rectangle tabArea =
                    new Rectangle(
                        SystemInformation.BorderSize.Width + offset.X +
                        (i * (tabContentWidth + tabLeftImage.Width + tabRightImage.Width - OverlapWidth)),
                        offset.Y + (TabHeight - tabCenterImage.Height), tabContentWidth + tabLeftImage.Width + tabRightImage.Width,
                        tabCenterImage.Height);

                // If we need to redraw the tab image, null out the property so that it will be recreated in the call to Render() below
                if (redraw)
                {
                    tab.TabImage = null;
                }

                // In this first pass, we only render the inactive tabs since we need the active tabs to show up on top of everything else
                if (!tab.Active)
                {
                    Render(graphicsContext, tab, tabArea, cursor, tabLeftImage, tabCenterImage, tabRightImage);
                }

                i--;
            }

            // In the second pass, render all of the active tabs identified in the previous pass
            foreach (Tuple <TitleBarTab, Rectangle> tab in activeTabs)
            {
                Image tabLeftImage = GetTabLeftImage(tab.Item1);
                tabCenterImage = GetTabCenterImage(tab.Item1);
                Image tabRightImage = GetTabRightImage(tab.Item1);

                Render(graphicsContext, tab.Item1, tab.Item2, cursor, tabLeftImage, tabCenterImage, tabRightImage);
            }

            _previousTabCount = tabs.Count;

            // Render the add tab button to the screen
            if (ShowAddButton && !IsTabRepositioning)
            {
                _addButtonArea =
                    new Rectangle(
                        (_previousTabCount *
                         (tabContentWidth + _activeLeftSideImage.Width + _activeRightSideImage.Width - OverlapWidth)) +
                        _activeRightSideImage.Width + AddButtonMarginLeft + offset.X,
                        AddButtonMarginTop + offset.Y + (TabHeight - tabCenterImage.Height), _addButtonImage.Width, _addButtonImage.Height);

                bool cursorOverAddButton = IsOverAddButton(cursor);

                graphicsContext.DrawImage(
                    cursorOverAddButton
                                                ? _addButtonHoverImage
                                                : _addButtonImage, _addButtonArea, 0, 0, cursorOverAddButton
                                                        ? _addButtonHoverImage.Width
                                                        : _addButtonImage.Width,
                    cursorOverAddButton
                                                ? _addButtonHoverImage.Height
                                                : _addButtonImage.Height, GraphicsUnit.Pixel);
            }
        }
Example #36
0
        /// <summary>
        /// Method to create a new tab when the add button in the title bar is clicked; creates a new <see cref="ConnectionWindow"/>.
        /// </summary>
        /// <returns>Tab for a new <see cref="ConnectionWindow"/> instance.</returns>
        public override TitleBarTab CreateTab()
        {
            _previouslyClickedTab = new TitleBarTab(this)
                                        {
                                            Content = new ConnectionWindow()
                                        };

            return _previouslyClickedTab;
        }
Example #37
0
 /// <summary>Tests whether the <paramref name="cursor" /> is hovering over the given <paramref name="tab" />.</summary>
 /// <param name="tab">Tab that we are to see if the cursor is hovering over.</param>
 /// <param name="cursor">Current location of the cursor.</param>
 /// <returns>
 /// True if the <paramref name="cursor" /> is within the <see cref="TitleBarTab.Area" /> of the <paramref name="tab" /> and is over a non- transparent
 /// pixel of <see cref="TitleBarTab.TabImage" />, false otherwise.
 /// </returns>
 protected virtual bool IsOverTab(TitleBarTab tab, Point cursor)
 {
     return(IsOverNonTransparentArea(tab.Area, tab.TabImage, cursor));
 }
Example #38
0
 /// <summary>
 /// Gets the image to use for the right side of the <paramref name="tab"/>.
 /// </summary>
 /// <param name="tab">Tab that we are retrieving the image for.</param>
 /// <returns>The image for the right side of <paramref name="tab"/>.</returns>
 protected virtual Image GetTabRightImage(TitleBarTab tab)
 {
     return(tab.Active
                         ? _activeRightSideImage
                         : _inactiveRightSideImage);
 }
Example #39
0
 /// <summary>Tests whether the <paramref name="cursor" /> is hovering over the given <paramref name="tab" />.</summary>
 /// <param name="tab">Tab that we are to see if the cursor is hovering over.</param>
 /// <param name="cursor">Current location of the cursor.</param>
 /// <returns>
 /// True if the <paramref name="cursor" /> is within the <see cref="TitleBarTab.Area" /> of the <paramref name="tab" /> and is over a non- transparent
 /// pixel of <see cref="TitleBarTab.TabImage" />, false otherwise.
 /// </returns>
 protected virtual bool IsOverTab(TitleBarTab tab, Point cursor)
 {
     return IsOverNonTransparentArea(tab.Area, tab.TabImage, cursor);
 }
Example #40
0
        /// <summary>Checks to see if the <paramref name="cursor" /> is over the <see cref="TitleBarTab.CloseButtonArea" /> of the given <paramref name="tab" />.</summary>
        /// <param name="tab">The tab whose <see cref="TitleBarTab.CloseButtonArea" /> we are to check to see if it contains <paramref name="cursor" />.</param>
        /// <param name="cursor">Current position of the cursor.</param>
        /// <returns>True if the <paramref name="tab" />'s <see cref="TitleBarTab.CloseButtonArea" /> contains <paramref name="cursor" />, false otherwise.</returns>
        public virtual bool IsOverCloseButton(TitleBarTab tab, Point cursor)
        {
            if (!tab.ShowCloseButton || _wasTabRepositioning)
            {
                return false;
            }

            Rectangle absoluteCloseButtonArea = new Rectangle(
                tab.Area.X + tab.CloseButtonArea.X, tab.Area.Y + tab.CloseButtonArea.Y, tab.CloseButtonArea.Width, tab.CloseButtonArea.Height);

            return absoluteCloseButtonArea.Contains(cursor);
        }
Example #41
0
        /// <summary>
        /// Handler method that's called after the user finishes renaming an item in <see cref="_bookmarksListView"/>.  Sets the <see cref="IConnection.Name"/>
        /// or <see cref="BookmarksFolder.Name"/> property and, if the user is setting the name for a newly-created bookmark, opens the option window for that
        /// bookmark.
        /// </summary>
        /// <param name="sender">Object from which this event originated, <see cref="_bookmarksListView"/> in this case.</param>
        /// <param name="e">Item being edited and its new label.</param>
        private void _bookmarksListView_AfterLabelEdit(object sender, LabelEditEventArgs e)
        {
            if (e.CancelEdit || String.IsNullOrEmpty(e.Label))
                return;

            if (_listViewConnections.ContainsKey(_bookmarksListView.Items[e.Item]))
            {
                IConnection connection = _listViewConnections[_bookmarksListView.Items[e.Item]];

                connection.Name = e.Label;

                // If this is a new connection (no Host property set) and the item label doesn't contain spaces, we default the host name for the connection to
                // the label name
                if (String.IsNullOrEmpty(connection.Host) && !e.Label.Contains(" "))
                {
                    connection.Host = e.Label;
                    _bookmarksListView.Items[e.Item].SubItems[1].Text = e.Label;
                }
            }

            else
                _listViewFolders[_bookmarksListView.Items[e.Item]].Name = e.Label;

            Save();

            if (_showOptionsAfterItemLabelEdit)
            {
                // Open the options window for the new bookmark if its name was set for the first time
                ListViewItem selectedItem = _bookmarksListView.SelectedItems[0];
                TitleBarTab optionsTab = new TitleBarTab(ParentTabs)
                                             {
                                                 Content = new OptionsWindow(ParentTabs)
                                                               {
                                                                   OptionsForms = new List<Form>
                                                                                      {
                                                                                          ConnectionFactory.CreateOptionsForm(_listViewConnections[selectedItem])
                                                                                      }
                                                               }
                                             };

                // When the options window is closed, update the value in the host column to what was supplied by the user
                optionsTab.Content.FormClosed += (o, args) => selectedItem.SubItems[1].Text = _listViewConnections[selectedItem].Host;

                ParentTabs.Tabs.Add(optionsTab);
                ParentTabs.ResizeTabContents(optionsTab);
                ParentTabs.SelectedTab = optionsTab;

                _showOptionsAfterItemLabelEdit = false;
            }

            _bookmarksListView.BeginInvoke(new Action(_bookmarksListView.Sort));
        }
Example #42
-1
        /// <summary>Constructor; initializes the window and constructs the tab thumbnail image to use when dragging.</summary>
        /// <param name="tab">Tab that was torn out of its parent window.</param>
        /// <param name="tabRenderer">Renderer instance to use when drawing the actual tab.</param>
        public TornTabForm(TitleBarTab tab, BaseTabRenderer tabRenderer)
        {
            _layeredWindow = new LayeredWindow();
            _initialized = false;

            // Set drawing styles
            SetStyle(ControlStyles.DoubleBuffer, true);

            // This should show up as a semi-transparent borderless window
            Opacity = 0.70;
            ShowInTaskbar = false;
            FormBorderStyle = FormBorderStyle.None;
            // ReSharper disable DoNotCallOverridableMethodsInConstructor
            BackColor = Color.Fuchsia;
            // ReSharper restore DoNotCallOverridableMethodsInConstructor
            TransparencyKey = Color.Fuchsia;
            AllowTransparency = true;

            Disposed += TornTabForm_Disposed;

            // Get the tab thumbnail (full size) and then draw the actual representation of the tab onto it as well
            Bitmap tabContents = tab.GetImage();
            Bitmap contentsAndTab = new Bitmap(tabContents.Width, tabContents.Height + tabRenderer.TabHeight, tabContents.PixelFormat);
            Graphics tabGraphics = Graphics.FromImage(contentsAndTab);

            tabGraphics.DrawImage(tabContents, 0, tabRenderer.TabHeight);

            bool oldShowAddButton = tabRenderer.ShowAddButton;

            tabRenderer.ShowAddButton = false;
            tabRenderer.Render(
                new List<TitleBarTab>
                {
                    tab
                }, tabGraphics, new Point(0, 0), new Point(0, 0), true);
            tabRenderer.ShowAddButton = oldShowAddButton;

            // Scale the thumbnail down to half size
            _tabThumbnail = new Bitmap(contentsAndTab.Width / 2, contentsAndTab.Height / 2, contentsAndTab.PixelFormat);
            Graphics thumbnailGraphics = Graphics.FromImage(_tabThumbnail);

            thumbnailGraphics.InterpolationMode = InterpolationMode.High;
            thumbnailGraphics.CompositingQuality = CompositingQuality.HighQuality;
            thumbnailGraphics.SmoothingMode = SmoothingMode.AntiAlias;
            thumbnailGraphics.DrawImage(contentsAndTab, 0, 0, _tabThumbnail.Width, _tabThumbnail.Height);

            Width = _tabThumbnail.Width - 1;
            Height = _tabThumbnail.Height - 1;

            _cursorOffset = new Point(tabRenderer.TabContentWidth / 4, tabRenderer.TabHeight / 4);

            SetWindowPosition(Cursor.Position);
        }