Beispiel #1
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, NotifyCollectionChangedEventArgs e)
        {
            SetFrameSize();

            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                for (int i = 0; i < e.NewItems.Count; i++)
                {
                    TitleBarTabItem currentTab = Tabs[i + e.NewStartingIndex];

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

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

            if (_overlay != null)
            {
                _overlay.Render(true);
            }
        }
Beispiel #2
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(TitleBarTabItem 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);
        }
Beispiel #3
0
        protected void HandleApplicationMouseLUp(Point mousePos)
        {
            // If we released the mouse button while we were dragging a torn tab, put that tab into a new window
            if (m_tornTab != null)
            {
                TitleBarTabItem tabToRelease = null;

                lock (m_tornTabLock)
                {
                    if (m_tornTab != null)
                    {
                        tabToRelease = m_tornTab;
                        m_tornTab    = null;
                    }
                }

                if (tabToRelease != null)
                {
                    TitleBarTabMainForm newWindow = (TitleBarTabMainForm)Activator.CreateInstance(m_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;
                    m_parentForm.ApplicationContext.OpenWindow(newWindow);

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

                    m_tornTabForm.Close();
                    m_tornTabForm = null;

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

            OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0));
        }
Beispiel #4
0
        /// <summary>Calls <see cref="CreateTab" />, adds the resulting tab to the <see cref="Tabs" /> collection, and activates it.</summary>
        public virtual void AddNewTab()
        {
            TitleBarTabItem newTab = CreateTab();

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

            SelectedTabIndex = _tabs.Count - 1;
        }
Beispiel #5
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 TitleBarTornTabForm(TitleBarTabItem tab, BaseTabRenderer tabRenderer, IMessageFilter messageFilter)
        {
            m_messageFilter = messageFilter;

            m_layeredWindow = new LayeredWindow();
            m_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 ListWithEvents <TitleBarTabItem>
            {
                tab
            }, tabGraphics, new Point(0, 0), new Point(0, 0), true);
            tabRenderer.ShowAddButton = oldShowAddButton;

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

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

            Width  = m_tabThumbnail.Width - 1;
            Height = m_tabThumbnail.Height - 1;

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

            SetWindowPosition(Cursor.Position);
        }
Beispiel #6
0
        /// <summary>Checks to see if the <paramref name="cursor" /> is over the <see cref="TitleBarTabItem.CloseButtonArea" /> of the given <paramref name="tab" />.</summary>
        /// <param name="tab">The tab whose <see cref="TitleBarTabItem.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="TitleBarTabItem.CloseButtonArea" /> contains <paramref name="cursor" />, false otherwise.</returns>
        public virtual bool IsOverCloseButton(TitleBarTabItem 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));
        }
Beispiel #7
0
        /// <summary>Resizes the <see cref="TitleBarTabItem.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="TitleBarTabItem.Content" /> form we should resize; if not specified, we default to
        /// <see cref="SelectedTab" />.</param>
        public void ResizeTabContents(TitleBarTabItem 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);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Callback for the <see cref="TabSelected" /> event.  Called when a <see cref="TitleBarTabItem" /> 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);
            }
        }
Beispiel #9
0
        /// <summary>
        /// Event handler that is called when a tab's <see cref="TitleBarTabItem.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="TitleBarTabItem" /> in this case).</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void TitleBarTabs_Closing(object sender, CancelEventArgs e)
        {
            TitleBarTabItem tab = (TitleBarTabItem)sender;

            CloseTab(tab);

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

            if (_overlay != null)
            {
                _overlay.Render(true);
            }
        }
Beispiel #10
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(TitleBarTabItem 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;
        }
Beispiel #11
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(TitleBarTabItem 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());
        }
Beispiel #12
0
        /// <summary>
        /// Called when a torn tab is dragged into the <see cref="TitleBarTabMainForm.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(TitleBarTabItem 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();
        }
Beispiel #13
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(TitleBarTabItem 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();
            }
        }
Beispiel #14
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 TitleBarTabItem OverTab(IEnumerable <TitleBarTabItem> tabs, Point cursor)
        {
            TitleBarTabItem overTab = null;

            foreach (TitleBarTabItem 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);
        }
Beispiel #15
0
        protected void HandleApplicationMouseMove(Point mousePos)
        {
            bool reRender = false;


            if (m_tornTab != null && m_dropAreas != null)
            {
                // ReSharper disable ForCanBeConvertedToForeach
                for (int i = 0; i < m_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 (m_dropAreas[i].Item2.Contains(mousePos))
                    {
                        TitleBarTabItem tabToCombine = null;

                        lock (m_tornTabLock)
                        {
                            if (m_tornTab != null)
                            {
                                tabToCombine = m_tornTab;
                                m_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
                            m_dropAreas[i1].Item1.TabRenderer.CombineTab(tabToCombine, mousePos);

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

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

            else if (!m_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 (m_isOverCloseButtonForTab != -1 &&
                    (m_isOverCloseButtonForTab >= m_parentForm.Tabs.Count ||
                     !m_parentForm.TabRenderer.IsOverCloseButton(m_parentForm.Tabs[m_isOverCloseButtonForTab], GetRelativeCursorPosition(mousePos))))
                {
                    reRender = true;
                    m_isOverCloseButtonForTab = -1;
                }

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

                            break;
                        }
                    }
                }
            }

            else
            {
                m_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(m_parentForm.TabRenderer.TabTearDragDistance, m_parentForm.TabRenderer.TabTearDragDistance);

                // If the cursor is outside the tear area, tear it away from the current window
                if (!dragArea.Contains(mousePos) && m_tornTab == null)
                {
                    lock (m_tornTabLock)
                    {
                        if (m_tornTab == null)
                        {
                            m_parentForm.TabRenderer.IsTabRepositioning = false;

                            // Clear the event handler subscriptions from the tab and then create a thumbnail representation of it to use when dragging
                            m_tornTab = m_parentForm.SelectedTab;
                            m_tornTab.ClearSubscriptions();
                            m_tornTabForm = new TitleBarTornTabForm(m_tornTab, m_parentForm.TabRenderer, this);
                        }
                    }

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

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

                        m_tornTabForm.Show();
                        m_dropAreas = (from window in m_parentForm.ApplicationContext.OpenWindows.Where(w => w.Tabs.Count > 0)
                                       select new Tuple <TitleBarTabMainForm, Rectangle>(window, window.TabDropArea)).ToArray();
                    }
                }
            }

            OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, mousePos.X, mousePos.Y, 0));

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

            if (reRender)
            {
                Render(mousePos, true);
            }
        }
Beispiel #16
0
        /// <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_NCPAINT:
            case WM.WM_PAINT:
                // If any of children need to be drawn, we need to draw title bar as well
                Render();
                System.Diagnostics.Debug.Print("Paint");
                break;

            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 (m_parentForm.TabRenderer.OverTab(m_parentForm.Tabs, relativeCursorPosition) == null &&
                    !m_parentForm.TabRenderer.IsOverAddButton(relativeCursorPosition))
                {
                    m_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
                    TitleBarTabItem clickedTab = m_parentForm.TabRenderer.OverTab(m_parentForm.Tabs, relativeCursorPosition);

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

                            Render();
                        }

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

                    m_parentForm.Activate();
                }

                break;

            case WM.WM_LBUTTONDBLCLK:
                m_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:
                Point relativeCursorPosition2 = GetRelativeCursorPosition(Cursor.Position);

                if (m_parentForm.TabRenderer.OverTab(m_parentForm.Tabs, relativeCursorPosition2) == null &&
                    !m_parentForm.TabRenderer.IsOverAddButton(relativeCursorPosition2))
                {
                    m_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
                    TitleBarTabItem clickedTab = m_parentForm.TabRenderer.OverTab(m_parentForm.Tabs, relativeCursorPosition2);

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

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

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

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

                break;

            default:
                base.WndProc(ref m);
                break;
            }
        }
Beispiel #17
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="TitleBarTabItem.Area" /> of the <paramref name="tab" /> and is over a non- transparent
 /// pixel of <see cref="TitleBarTabItem.TabImage" />, false otherwise.
 /// </returns>
 protected virtual bool IsOverTab(TitleBarTabItem tab, Point cursor)
 {
     return(IsOverNonTransparentArea(tab.Area, tab.TabImage, cursor));
 }
Beispiel #18
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(ListWithEvents <TitleBarTabItem> 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    = (_parentWindow.ClientRectangle.Width - offset.X -
                                    (ShowAddButton
                                                     ? _addButtonImage.Width + AddButtonMarginLeft +
                                     AddButtonMarginRight
                                                     : 0) - (tabs.Count() * OverlapWidth) -
                                    (_parentWindow.ControlBox
                                                     ? SystemInformation.CaptionButtonSize.Width
                                                     : 0) -
                                    (_parentWindow.MinimizeBox
                                                     ? SystemInformation.CaptionButtonSize.Width
                                                     : 0) -
                                    (_parentWindow.MaximizeBox
                                                     ? SystemInformation.CaptionButtonSize.Width
                                                     : 0));
            _maxTabArea.Height = _activeCenterImage.Height;

            // 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 <TitleBarTabItem, Rectangle> > activeTabs = new List <Tuple <TitleBarTabItem, Rectangle> >();

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

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

            if (selectedIndex != -1)
            {
                Rectangle tabArea = new Rectangle(
                    SystemInformation.BorderSize.Width + offset.X +
                    (selectedIndex * (tabContentWidth + _activeLeftSideImage.Width + _activeRightSideImage.Width - OverlapWidth)),
                    offset.Y, tabContentWidth + _activeLeftSideImage.Width + _activeRightSideImage.Width,
                    _activeCenterImage.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)
                    {
                        TitleBarTabItem tab = tabs[selectedIndex];

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

                activeTabs.Add(new Tuple <TitleBarTabItem, 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 (TitleBarTabItem tab in ((IEnumerable <TitleBarTabItem>)tabs).Reverse())
            {
                Rectangle tabArea =
                    new Rectangle(
                        SystemInformation.BorderSize.Width + offset.X +
                        (i * (tabContentWidth + _activeLeftSideImage.Width + _activeRightSideImage.Width - OverlapWidth)),
                        offset.Y, tabContentWidth + _activeLeftSideImage.Width + _activeRightSideImage.Width,
                        _activeCenterImage.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);
                }

                i--;
            }

            // In the second pass, render all of the active tabs identified in the previous pass
            foreach (Tuple <TitleBarTabItem, Rectangle> tab in activeTabs)
            {
                Render(graphicsContext, tab.Item1, tab.Item2, cursor);
            }

            _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, _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);
            }
        }
Beispiel #19
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>
        protected virtual void Render(Graphics graphicsContext, TitleBarTabItem 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
                });
            }
        }