public override TitleBarTab CreateTab() { TitleBarTab tab = new TitleBarTab(this); tab.Content = new TabWindow(); Console.WriteLine("tab window is created"); return tab; }
/// <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); }
/// <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); }
/// <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); }
/// <summary>Hook callback to process <see cref="WM.WM_MOUSEMOVE" /> messages to highlight/un-highlight the close button on each tab.</summary> /// <param name="nCode">The message being received.</param> /// <param name="wParam">Additional information about the message.</param> /// <param name="lParam">Additional information about the message.</param> /// <returns>A zero value if the procedure processes the message; a nonzero value if the procedure ignores the message.</returns> protected IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode >= 0 && (int) WM.WM_MOUSEMOVE == (int) wParam) { MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT) Marshal.PtrToStructure(lParam, typeof (MSLLHOOKSTRUCT)); Point cursorPosition = new Point(hookStruct.pt.x, hookStruct.pt.y); bool reRender = false; if (_tornTab != 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)) { lock (_tornTabLock) { if (_tornTab != null) { _dropAreas[i].Item1.TabRenderer.CombineTab(_tornTab, cursorPosition); _tornTab = null; _tornTabForm.Close(); _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; } // 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 { _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); _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(); } } } } OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, cursorPosition.X, cursorPosition.Y, 0)); if (_parentForm.TabRenderer.IsTabRepositioning) reRender = true; if (reRender) 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) { lock (_tornTabLock) { if (_tornTab != null) { 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; } _tornTab.Parent = newWindow; _parentForm.ApplicationContext.OpenWindow(newWindow); newWindow.Show(); newWindow.Tabs.Add(_tornTab); newWindow.SelectedTabIndex = 0; newWindow.ResizeTabContents(); _tornTab = null; _tornTabForm.Close(); _tornTabForm = null; if (_parentForm.Tabs.Count == 0) _parentForm.Close(); } } } OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, Cursor.Position.X, Cursor.Position.Y, 0)); } return User32.CallNextHookEx(_hookId, nCode, wParam, lParam); }
/// <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) { // ReSharper disable PossibleInvalidOperationException Point cursorPosition = new Point(hookStruct.Value.pt.x, hookStruct.Value.pt.y); // ReSharper restore PossibleInvalidOperationException bool reRender = false; if (_tornTab != 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) { // 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)))); } } }
/// <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 (!closingTab.Content.IsDisposed && AeroPeekEnabled) TaskbarManager.Instance.TabbedThumbnail.RemoveThumbnailPreview(closingTab.Content); if (Tabs.Count == 0 && ExitOnLastTabClose) Close(); }
/// <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; }
/// <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; }
/// <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); }
/// <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; }
/// <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; }
/// <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); }
/// <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; }
/// <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; }
/// <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 }); } }
/// <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 _tabClickOffset = _parentWindow.Tabs.First().Area.Width / 2; 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(); }
/// <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); } }
/// <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 = new TabbedThumbnail(Handle, tab.Content) { Title = tab.Content.Text, Tooltip = tab.Content.Text }; preview.SetWindowIcon(tab.Content.Icon); 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; }
/// <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)); }