//Except where stated all code and programs in this project are the copyright of Jim Blackler, 2008.
//jimblackler@gmail.com
//
//This is free software. Libraries and programs are distributed under the terms of the GNU Lesser
//General Public License. Please see the files COPYING and COPYING.LESSER.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace MiscControls
{
///
/// A tab control in which the user can re-order the tabs by dragging the mouse
///
public partial class ReorderableTabControl : TabControl
{
///
/// Make a reorderable tab control
///
public ReorderableTabControl()
{
InitializeComponent();
}
bool dragging = false;
TabPage lastDraggedTabPage;
private void ReorderableTabControl_MouseDown(object sender, MouseEventArgs e)
{
if ((e.Button & MouseButtons.Left) != 0)
{
dragging = true;
lastDraggedTabPage = null;
}
}
private void ReorderableTabControl_MouseMove(object sender, MouseEventArgs e)
{
if (!dragging)
return; // user does not have button held down
TabPage overTabPage = null;
int overTabPageIdx = -1;
int selectedIndex = TabPages.IndexOf(SelectedTab);
Rectangle selectedRect = GetTabRect(selectedIndex);
// Find the tab page that the mouse is over
int index = 0;
foreach (TabPage scanTabPage in TabPages)
{
Rectangle rect = GetTabRect(index);
if (selectedRect.Width < rect.Width)
{
// Lessen the strange 'over shifting' effect of moving a small tab over
// a larger one
int newWidth = (selectedRect.Width + rect.Width) / 2;
// Real hot spot width is average of two tab sizes
if (rect.X > selectedRect.X) // moving right on the tab display
{
rect.X += rect.Width - newWidth;
}
rect.Width = newWidth;
}
if (rect.Contains(PointToClient(MousePosition)))
{
overTabPage = scanTabPage;
overTabPageIdx = index;
break;
}
index++;
}
if (overTabPage == lastDraggedTabPage)
return;
if (overTabPage == null)
return; // not over a tab page
if (SelectedTab == overTabPage)
return; // still over original tab page .. nothing to do
SuspendLayout();
// Revised method from section commented out below
TabPages[overTabPageIdx] = SelectedTab;
TabPages[selectedIndex] = overTabPage;
SelectedIndex = overTabPageIdx;
// Simply swap the tab pages (this works because they are adjacent)
//TabPages.Remove(overTabPage);
//TabPages.Insert(selectedIndex, overTabPage);
ResumeLayout();
}
///
/// The user has lifted the button - stop dragging
///
private void ReorderableTabControl_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
}
}
}