123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616 |
- using System;
- using System.Drawing;
- using System.Windows.Forms;
- using System.Collections;
- using System.Drawing.Drawing2D;
- using FastReport.Utils;
- namespace FastReport.Controls
- {
- internal class Tab
- {
- public FRTabStrip TabControl { get; set; }
- public string Text { get; set; }
- public object Tag { get; set; }
- public Image Image { get; set; }
- public bool Visible { get; set; }
- public bool CloseButton { get; set; }
- public bool AllowMove { get; set; }
- public Rectangle DisplayRectangle { get; set; }
- public int CalcWidth()
- {
- if (!Visible)
- return 0;
- int _2 = TabControl.LogicalToDevice(2);
- int _16 = TabControl.LogicalToDevice(16);
- int result = _2;
- if (Image != null)
- result += _16;
- #if AVALONIA
- TextRenderer.FontScale = (float)TabControl.DpiScale;
- #endif
- result += _2 + TextRenderer.MeasureText(Text, TabControl.Font).Width + _2;
- if (CloseButton)
- result += _16 + _2;
- return result;
- }
- public Tab()
- {
- AllowMove = true;
- CloseButton = true;
- Visible = true;
- }
- public Tab(string text) : this()
- {
- Text = text;
- }
- public Tab(string text, Image image) : this(text)
- {
- Image = image;
- }
- }
- internal class TabCollection : CollectionBase
- {
- private FRTabStrip FOwner;
- public Tab this[int index]
- {
- get { return List[index] as Tab; }
- set { List[index] = value; }
- }
- public void AddRange(Tab[] range)
- {
- foreach (Tab t in range)
- {
- Add(t);
- }
- }
- public int Add(Tab value)
- {
- return List.Add(value);
- }
- public void Insert(int index, Tab value)
- {
- List.Insert(index, value);
- }
- public void Remove(Tab value)
- {
- List.Remove(value);
- }
- public int IndexOf(Tab value)
- {
- return List.IndexOf(value);
- }
- public bool Contains(Tab value)
- {
- return List.Contains(value);
- }
- protected override void OnInsert(int index, Object value)
- {
- if (FOwner != null)
- {
- (value as Tab).TabControl = FOwner;
- }
- }
- public TabCollection(FRTabStrip owner)
- {
- FOwner = owner;
- }
- }
- internal delegate void TabMovedEventHandler(object sender, TabMovedEventArgs e);
- internal class TabMovedEventArgs
- {
- public int OldIndex;
- public int NewIndex;
- public TabMovedEventArgs(int oldIndex, int newIndex)
- {
- OldIndex = oldIndex;
- NewIndex = newIndex;
- }
- }
- internal enum TabOrientation
- {
- Top,
- Bottom
- }
- internal class FRTabStrip : Control
- {
- private int selectedTabIndex;
- private bool scrollButtonsVisible;
- private int highlightTabIndex;
- private bool highlightLeftBtn;
- private bool highlightRightBtn;
- private bool highlightCloseButton;
- private int offset;
- private int saveTabIndex;
- private bool movingTab;
- private bool tabMoved;
- private int mouseOffset;
- private TabOrientation tabOrientation;
- private TabStripColors style = new TabStripColors();
- public TabCollection Tabs { get; }
- public int SelectedTabIndex
- {
- get { return selectedTabIndex; }
- set
- {
- if (value < 0)
- value = -1;
- if (value > Tabs.Count - 1)
- value = Tabs.Count - 1;
- selectedTabIndex = value;
- EnsureTabVisible();
- Refresh();
- SelectedTabChanged?.Invoke(this, null);
- }
- }
- public Tab SelectedTab
- {
- get
- {
- if (SelectedTabIndex == -1 || SelectedTabIndex >= Tabs.Count)
- return null;
- return Tabs[SelectedTabIndex];
- }
- set
- {
- SelectedTabIndex = Tabs.IndexOf(value);
- }
- }
- public bool AllowTabReorder { get; set; }
- public TabOrientation TabOrientation
- {
- get { return tabOrientation; }
- set
- {
- tabOrientation = value;
- Refresh();
- }
- }
- public TabStripColors Style
- {
- get { return style; }
- set
- {
- style = value;
- Refresh();
- }
- }
- public event EventHandler SelectedTabChanged;
- public event EventHandler TabClosed;
- public event TabMovedEventHandler TabMoved;
- private void EnsureTabVisible()
- {
- if (Width == 0)
- return;
- Tab tab = SelectedTab;
- if (tab == null)
- return;
-
- int tabsWidth = CalcItems();
- int _4 = this.LogicalToDevice(4);
- int add = scrollButtonsVisible ? this.LogicalToDevice(40) : 0;
- if (tab.DisplayRectangle.Left < 0)
- offset += -tab.DisplayRectangle.Left + _4;
- else if (tab.DisplayRectangle.Right > Width - add)
- offset -= tab.DisplayRectangle.Right - (Width - add) + _4;
- if (offset > 0)
- offset = 0;
- if (tabsWidth < DisplayRectangle.Width)
- offset = 0;
- Refresh();
- }
- private int CalcItems()
- {
- int _3 = this.LogicalToDevice(3);
- int _4 = this.LogicalToDevice(4);
- int x = _4 + offset;
- int tabsWidth = 0;
- foreach (Tab tab in Tabs)
- {
- if (!tab.Visible)
- continue;
- int width = tab.CalcWidth();
- if (TabOrientation == TabOrientation.Top)
- tab.DisplayRectangle = new Rectangle(x, _3, width, Height - _3);
- else
- tab.DisplayRectangle = new Rectangle(x, 0, width, Height - _4);
- x += width;
- tabsWidth += width;
- }
- return tabsWidth;
- }
- private void HighlightButton(Graphics g, int x, int y)
- {
- if (!scrollButtonsVisible)
- return;
- int _16 = this.LogicalToDevice(16);
- using (var brush = new SolidBrush(Color.FromArgb(193, 210, 238)))
- using (var pen = new Pen(Color.FromArgb(49, 106, 197), this.LogicalToDevice(1f)))
- {
- g.FillRectangle(brush, x, y, _16, _16);
- g.DrawRectangle(pen, x, y, _16, _16);
- }
- }
- private void ScrollLeft()
- {
- if (offset < 0)
- {
- offset += SelectedTab.DisplayRectangle.Width;
- if (offset > 0)
- offset = 0;
- }
- Refresh();
- }
- private void ScrollRight()
- {
- int tabsWidth = 0;
- for (int i = 0; i < Tabs.Count - 1; i++)
- tabsWidth += Tabs[i].DisplayRectangle.Width;
- if (-offset < tabsWidth)
- offset -= SelectedTab.DisplayRectangle.Width;
- Refresh();
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- CalcItems();
- Graphics g = e.Graphics;
- Pen pen = new Pen(style.Border, this.LogicalToDevice(1f));
- LinearGradientBrush brush = new LinearGradientBrush(DisplayRectangle,
- style.GradientBegin,
- style.GradientEnd,
- LinearGradientMode.Vertical);
- g.FillRectangle(brush, DisplayRectangle);
-
- Brush activeBrush = new SolidBrush(style.ActiveTabBackground);
- // draw all tabs except selected one
- int tabsWidth = 0;
- for (int i = 0; i < Tabs.Count; i++)
- {
- Tab tab = Tabs[i];
- if (!tab.Visible)
- continue;
- Rectangle rect = tab.DisplayRectangle;
- tabsWidth += rect.Width;
- if (i != SelectedTabIndex)
- DrawTab(g, i, pen, activeBrush);
- }
- // draw top/bottom line
- using (Brush lineBrush = new SolidBrush(style.Border))
- {
- int h = this.LogicalToDevice(style.BorderWidth);
- if (TabOrientation == TabOrientation.Top)
- g.FillRectangle(lineBrush, 0, Height - h, Width, h);
- else
- g.FillRectangle(lineBrush, 0, 0, Width, h);
- }
- // draw active tab
- if (SelectedTabIndex != -1)
- DrawTab(g, SelectedTabIndex, pen, activeBrush);
- scrollButtonsVisible = tabsWidth > Width;
- if (scrollButtonsVisible)
- DrawScrollButtons(g, brush);
- pen.Dispose();
- brush.Dispose();
- activeBrush.Dispose();
- }
- private void DrawTab(Graphics g, int i, Pen pen, Brush brush)
- {
- int _1 = this.LogicalToDevice(1);
- int _2 = this.LogicalToDevice(2);
- int _3 = this.LogicalToDevice(3);
- int _4 = this.LogicalToDevice(4);
- int _5 = this.LogicalToDevice(5);
- int _16 = this.LogicalToDevice(16);
- Tab tab = Tabs[i];
- Rectangle rect = tab.DisplayRectangle;
- int x = rect.Left;
- if (i == SelectedTabIndex || i == highlightTabIndex)
- {
- g.FillRectangle(brush, rect.Left, rect.Top, rect.Width, rect.Height);
- if (TabOrientation == TabOrientation.Top)
- {
- g.DrawLines(pen, new Point[]
- {
- new Point(rect.Left, rect.Bottom),
- new Point(rect.Left, rect.Top),
- new Point(rect.Right, rect.Top),
- new Point(rect.Right, rect.Bottom)
- });
- }
- else
- {
- g.DrawLines(pen, new Point[]
- {
- new Point(rect.Left, rect.Top),
- new Point(rect.Left, rect.Bottom),
- new Point(rect.Right, rect.Bottom),
- new Point(rect.Right, rect.Top)
- });
- }
- }
- else if (i < Tabs.Count - 1)
- {
- g.DrawLine(pen, rect.Right, rect.Top + _3, rect.Right, rect.Bottom - _3);
- }
- if (tab.Image != null)
- {
- g.DrawImage(tab.Image, rect.Left + _3, rect.Top + _3);
- x += _16;
- }
- TextRenderer.DrawText(g, tab.Text, Font, new Point(x + _4, rect.Top + _2 + 1),
- i == SelectedTabIndex || i == highlightTabIndex ? style.ActiveTabForeground : style.InactiveTabForeground);
- if (tab.CloseButton)
- DrawCloseButton(g, rect.Right - _16, rect.Top + _4, i);
- }
- private void DrawCloseButton(Graphics g, int x, int y, int i)
- {
- int btnSize = this.LogicalToDevice(13);
- int _3 = this.LogicalToDevice(3);
- bool isHighlight = highlightCloseButton && i == highlightTabIndex;
- if (isHighlight)
- {
- using (var brush = new SolidBrush(Color.FromArgb(196, 43, 28)))
- g.FillRectangle(brush, new Rectangle(x, y, btnSize, btnSize));
- }
- using (var p = new Pen(
- isHighlight ? Color.White :
- i == SelectedTabIndex || i == highlightTabIndex ? style.ActiveTabForeground : style.InactiveTabForeground, this.LogicalToDevice(1f)))
- {
- g.DrawLine(p, x + _3, y + _3, x + btnSize - _3 - 1, y + btnSize - _3 - 1);
- g.DrawLine(p, x + _3, y + btnSize - _3 - 1, x + btnSize - _3 - 1, y + _3);
- }
- }
- private void DrawScrollButtons(Graphics g, Brush brush)
- {
- int _4 = this.LogicalToDevice(4);
- int _20 = this.LogicalToDevice(20);
- int _22 = this.LogicalToDevice(22);
- int _38 = this.LogicalToDevice(38);
- int _40 = this.LogicalToDevice(40);
- g.FillRectangle(brush, Width - _40, 1, _40, Height - 2);
- if (highlightLeftBtn)
- HighlightButton(g, Width - _38, _4);
- g.DrawImage(this.GetImage(186), Width - _38, _4);
- if (highlightRightBtn)
- HighlightButton(g, Width - _20, _4);
- g.DrawImage(this.GetImage(187), Width - _22, _4);
- }
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
- int _6 = this.LogicalToDevice(6);
- int _16 = this.LogicalToDevice(16);
- int _20 = this.LogicalToDevice(20);
- int _24 = this.LogicalToDevice(24);
- int _38 = this.LogicalToDevice(38);
- movingTab = false;
- if (scrollButtonsVisible && e.X > Width - _38 && e.X < Width - _24)
- {
- ScrollLeft();
- }
- else if (scrollButtonsVisible && e.X > Width - _20 && e.X < Width - _6)
- {
- ScrollRight();
- }
- else
- {
- Tab tab = TabAt(e.X);
- if (tab != null)
- {
- if (tab.CloseButton && e.X > tab.DisplayRectangle.Right - _16 && e.X < tab.DisplayRectangle.Right)
- {
- // close button, handle in mouseup
- return;
- }
- SelectedTab = tab;
- movingTab = true;
- }
- }
- saveTabIndex = SelectedTabIndex;
- tabMoved = false;
- mouseOffset = 0;
- }
- private void CloseTab(Tab tab)
- {
- TabClosed?.Invoke(tab, null);
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- int _6 = this.LogicalToDevice(6);
- int _16 = this.LogicalToDevice(16);
- int _20 = this.LogicalToDevice(20);
- int _24 = this.LogicalToDevice(24);
- int _38 = this.LogicalToDevice(38);
- if (e.Button == MouseButtons.None)
- {
- bool needRefresh = false;
- if (scrollButtonsVisible)
- {
- bool b = e.X > Width - _38 && e.X < Width - _24;
- if (b != highlightLeftBtn)
- {
- highlightLeftBtn = b;
- needRefresh = true;
- }
- b = e.X > Width - _20 && e.X < Width - _6;
- if (highlightRightBtn != b)
- {
- highlightRightBtn = b;
- needRefresh = true;
- }
- }
- int tabIndex = -1;
- Tab tab = TabAt(e.X);
- if (tab != null)
- {
- tabIndex = Tabs.IndexOf(tab);
- bool b = e.X > tab.DisplayRectangle.Right - _16 && e.X < tab.DisplayRectangle.Right;
- if (b != highlightCloseButton)
- {
- highlightCloseButton = b;
- needRefresh = true;
- }
- }
- if (highlightTabIndex != tabIndex)
- {
- highlightTabIndex = tabIndex;
- needRefresh = true;
- }
- if (needRefresh)
- Refresh();
- }
- else if (e.Button == MouseButtons.Left && movingTab && AllowTabReorder)
- {
- Tab oldTab = SelectedTab;
- Tab newTab = TabAt(e.X + mouseOffset);
- if (oldTab != null && newTab != null && newTab != oldTab && newTab.AllowMove && oldTab.AllowMove)
- {
- int oldIndex = Tabs.IndexOf(oldTab);
- int newIndex = Tabs.IndexOf(newTab);
- Tabs.Remove(oldTab);
- Tabs.Insert(newIndex, oldTab);
- Refresh();
- SelectedTabIndex = newIndex;
- tabMoved = true;
- #if !(WPF || AVALONIA)
- if (oldIndex < newIndex)
- mouseOffset = oldTab.DisplayRectangle.Left - e.X;
- else
- mouseOffset = e.X - oldTab.DisplayRectangle.Right;
- #endif
- }
- }
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- if (tabMoved)
- {
- TabMoved?.Invoke(this, new TabMovedEventArgs(saveTabIndex, SelectedTabIndex));
- }
- else
- {
- int _16 = this.LogicalToDevice(16);
- Tab tab = TabAt(e.X);
- if (tab != null)
- {
- if (tab.CloseButton && e.X > tab.DisplayRectangle.Right - _16 && e.X < tab.DisplayRectangle.Right)
- CloseTab(tab);
- }
- }
- base.OnMouseUp(e);
- }
- protected override void OnMouseLeave(EventArgs e)
- {
- base.OnMouseLeave(e);
- if (highlightLeftBtn || highlightRightBtn || highlightTabIndex != -1)
- {
- highlightLeftBtn = false;
- highlightRightBtn = false;
- highlightCloseButton = false;
- highlightTabIndex = -1;
- Refresh();
- }
- }
- public Tab TabAt(int x)
- {
- foreach (Tab tab in Tabs)
- {
- if (!tab.Visible)
- continue;
- if (x >= tab.DisplayRectangle.Left && x <= tab.DisplayRectangle.Right)
- return tab;
- }
- return null;
- }
- public FRTabStrip()
- {
- Tabs = new TabCollection(this);
- scrollButtonsVisible = true;
- AllowTabReorder = true;
- highlightTabIndex = -1;
- SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw, true);
- Height = 24;
- }
- }
- }
|