Skip to content

Commit

Permalink
Refactor drawing logic and draw unsaved document page indicator
Browse files Browse the repository at this point in the history
- Introduce `ImageRect` and `UsavedRect`;
- Calculate rectangles once in `CalculateTab` (except for
`closeForegroundRect` which is calculated while drawing it);
- Restructure calculations element by element;
- Each of the element has valid location and size (even though it can be
 empty);
- (Hopefully) simplify calculations by using `PointF` and `RectangleF`
methods;
- Simplify drawing of the close button.
  • Loading branch information
ievgen-baida committed Feb 29, 2024
1 parent 44b1ac3 commit 144e2b8
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 33 deletions.
2 changes: 2 additions & 0 deletions src/Eto.Gtk/Forms/Controls/DocumentPageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public bool Closable
set { closeButton.Visible = value; }
}

public bool HasUnsavedChanges { get; set; }

public Image Image
{
get { return image; }
Expand Down
73 changes: 40 additions & 33 deletions src/Eto/Forms/ThemedControls/ThemedDocumentControlHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -696,33 +696,35 @@ void Drawable_Paint(object sender, PaintEventArgs e)
}
}

void CalculateTab(ThemedDocumentPageHandler tab, int i, ref float posx)
void CalculateTab(ThemedDocumentPageHandler tab, int i, ref float posX)
{
var tabPadding = TabPadding;
var textSize = string.IsNullOrEmpty(tab.Text) ? Size.Empty : Size.Ceiling(Font.MeasureString(tab.Text));
var size = textSize;
var prevnextsel = mousePos.X > nextPrevWidth || i == -1;
var textoffset = 0;
if (tab.Image != null)
var tabLocation = new PointF(posX, 0);
if (i == selectedIndex && draggingLocation != null)
{
textoffset = maxImageSize.Width + tabPadding.Left;
size.Width += textoffset;
tabLocation.Offset(mousePos.X - draggingLocation.Value.X, 0);
}

var closesize = (int)Math.Floor(tabDrawable.Height * 0.6);
var tabRect = new RectangleF(posx, 0, size.Width + (tab.Closable ? closesize + tabPadding.Horizontal + tabPadding.Right : tabPadding.Horizontal), tabDrawable.Height);
var imageLocation = new PointF(tabLocation.X + TabPadding.Left, (tabDrawable.Height - maxImageSize.Height) / 2f);
var imageSize = tab.Image is null ? Size.Empty : maxImageSize;
tab.ImageRect = new RectangleF(imageLocation, imageSize);

if (i == selectedIndex && draggingLocation != null)
{
tabRect.Offset(mousePos.X - draggingLocation.Value.X, 0);
}
var textSize = string.IsNullOrEmpty(tab.Text) ? Size.Empty : Size.Ceiling(Font.MeasureString(tab.Text));
var textLocation = new PointF(tab.ImageRect.Right + (imageSize.IsEmpty ? 0 : TabPadding.Left), (tabDrawable.Height - textSize.Height) / 2);
tab.TextRect = new RectangleF(textLocation, textSize);

tab.Rect = tabRect;
var unsavedSize = tab.HasUnsavedChanges ? new Size(6, 6) : Size.Empty;
var unsavedLocation = new PointF(tab.TextRect.Right + (tab.HasUnsavedChanges ? TabPadding.Right : 0), (tabDrawable.Height - unsavedSize.Height) / 2);
tab.UnsavedRect = new RectangleF(unsavedLocation, unsavedSize);

tab.CloseRect = new RectangleF(tabRect.X + tab.Rect.Width - tabPadding.Right - closesize, (tabDrawable.Height - closesize) / 2, closesize, closesize);
tab.TextRect = new RectangleF(tabRect.X + tabPadding.Left + textoffset, (tabDrawable.Height - size.Height) / 2, textSize.Width, textSize.Height);
var closeSize = tab.Closable
? (int)Math.Floor(tabDrawable.Height * 0.6)
: 0;
var closeLocation = new PointF(tab.UnsavedRect.Right + (tab.Closable ? TabPadding.Right : 0), (tabDrawable.Height - closeSize) / 2);
tab.CloseRect = new RectangleF(closeLocation, new SizeF(closeSize, closeSize));

posx += tab.Rect.Width;
tab.Rect = new RectangleF(tabLocation, new SizeF(tab.CloseRect.Right + TabPadding.Right - tabLocation.X, tabDrawable.Height));

posX += tab.Rect.Width;
}

bool IsCloseSelected(ThemedDocumentPageHandler tab)
Expand All @@ -734,11 +736,6 @@ bool IsCloseSelected(ThemedDocumentPageHandler tab)
void DrawTab(Graphics g, ThemedDocumentPageHandler tab, int i)
{
var prevnextsel = mousePos.X > nextPrevWidth || i == -1;
var closeSelected = IsCloseSelected(tab);
var tabRect = tab.Rect;
var textRect = tab.TextRect;
var closerect = tab.CloseRect;
var closemargin = closerect.Height / 4;

var textcolor = Enabled ? TabForegroundColor : DisabledForegroundColor;
var backcolor = TabBackgroundColor;
Expand All @@ -747,33 +744,43 @@ void DrawTab(Graphics g, ThemedDocumentPageHandler tab, int i)
textcolor = Enabled ? TabHighlightForegroundColor : DisabledForegroundColor;
backcolor = TabHighlightBackgroundColor;
}
else if (draggingLocation == null && tabRect.Contains(mousePos) && prevnextsel && Enabled)
else if (draggingLocation == null && tab.Rect.Contains(mousePos) && prevnextsel && Enabled)
{
textcolor = TabHoverForegroundColor;
backcolor = TabHoverBackgroundColor;
}

g.FillRectangle(backcolor, tabRect);
if (tab.Image != null)
g.FillRectangle(backcolor, tab.Rect);
g.DrawText(Font, textcolor, tab.TextRect.Location, tab.Text);

if (tab.Image is not null)
{
g.SaveTransform();
g.ImageInterpolation = ImageInterpolation.High;
g.DrawImage(tab.Image, tabRect.X + TabPadding.Left, (tabDrawable.Height - maxImageSize.Height) / 2, maxImageSize.Width, maxImageSize.Height);
g.DrawImage(tab.Image, tab.ImageRect);
g.RestoreTransform();
}
g.DrawText(Font, textcolor, textRect.Location, tab.Text);

if (tab.HasUnsavedChanges)
{
g.FillEllipse(UnsavedBackgroundColor, tab.UnsavedRect);
}

if (tab.Closable)
{
var closeSelected = IsCloseSelected(tab);

var closeBackground = closeSelected ? CloseHighlightBackgroundColor : CloseBackgroundColor;
if (closeCornerRadius > 0)
g.FillPath(closeBackground, GraphicsPath.GetRoundRect(closerect, closeCornerRadius));
g.FillPath(closeBackground, GraphicsPath.GetRoundRect(tab.CloseRect, closeCornerRadius));
else
g.FillRectangle(closeBackground, closerect);
g.FillRectangle(closeBackground, tab.CloseRect);

var closeMargin = (int)tab.CloseRect.Height / 4;
var closeForegroundRect = RectangleF.Inset(tab.CloseRect, new PaddingF(closeMargin));
var closeForeground = Enabled ? closeSelected ? CloseHighlightForegroundColor : CloseForegroundColor : DisabledForegroundColor;
g.DrawLine(closeForeground, closerect.X + closemargin, closerect.Y + closemargin, closerect.X + closerect.Width - 1 - closemargin, closerect.Y + closerect.Height - 1 - closemargin);
g.DrawLine(closeForeground, closerect.X + closemargin, closerect.Y + closerect.Height - 1 - closemargin, closerect.X + closerect.Width - 1 - closemargin, closerect.Y + closemargin);
g.DrawLine(closeForeground, closeForegroundRect.TopLeft, closeForegroundRect.BottomRight);
g.DrawLine(closeForeground, closeForegroundRect.TopRight, closeForegroundRect.BottomLeft);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/Eto/Forms/ThemedControls/ThemedDocumentPageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,13 @@ public bool HasUnsavedChanges

internal RectangleF Rect { get; set; }

internal RectangleF UnsavedRect { get; set; }

internal RectangleF CloseRect { get; set; }

internal RectangleF TextRect { get; set; }

internal RectangleF ImageRect { get; set; }

void Update() => DocControl?.Update(this);
}

0 comments on commit 144e2b8

Please sign in to comment.