mirror of
https://github.com/greenshot/greenshot
synced 2025-07-16 10:03:44 -07:00
Fixed the target-gripper logic (needed for the speech bubble) and made the drawing of Rectangles / Ellipses possible without extending the container (making it possible to use different shapes depending on a variable). The new containers (SpeechBubble & StepLabel) are mostly working with this change, default colors/sizes should be decided upon and translations/icons are still missing. There is one bug with the Speechbubble when resizing (right before left, bottom before top), should not be a show-stopper but needs lookin into.
This commit is contained in:
parent
ff3f898f54
commit
aa5893fc77
6 changed files with 240 additions and 124 deletions
|
@ -46,7 +46,7 @@ namespace Greenshot.Drawing {
|
|||
public abstract class DrawableContainer : AbstractFieldHolderWithChildren, INotifyPropertyChanged, IDrawableContainer {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(DrawableContainer));
|
||||
protected static readonly EditorConfiguration editorConfig = IniConfig.GetIniSection<EditorConfiguration>();
|
||||
private bool isMadeUndoable = false;
|
||||
private bool _isMadeUndoable = false;
|
||||
|
||||
protected EditStatus _defaultEditMode = EditStatus.DRAWING;
|
||||
public EditStatus DefaultEditMode {
|
||||
|
@ -141,45 +141,45 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
|
||||
private int left = 0;
|
||||
private int _left = 0;
|
||||
public int Left {
|
||||
get { return left; }
|
||||
get { return _left; }
|
||||
set {
|
||||
if(value != left) {
|
||||
left = value;
|
||||
if(value != _left) {
|
||||
_left = value;
|
||||
DoLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int top = 0;
|
||||
private int _top = 0;
|
||||
public int Top {
|
||||
get { return top; }
|
||||
get { return _top; }
|
||||
set {
|
||||
if(value != top) {
|
||||
top = value;
|
||||
if(value != _top) {
|
||||
_top = value;
|
||||
DoLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int width = 0;
|
||||
private int _width = 0;
|
||||
public int Width {
|
||||
get { return width; }
|
||||
get { return _width; }
|
||||
set {
|
||||
if(value != width) {
|
||||
width = value;
|
||||
if(value != _width) {
|
||||
_width = value;
|
||||
DoLayout();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int height = 0;
|
||||
private int _height = 0;
|
||||
public int Height {
|
||||
get { return height; }
|
||||
get { return _height; }
|
||||
set {
|
||||
if(value != height) {
|
||||
height = value;
|
||||
if(value != _height) {
|
||||
_height = value;
|
||||
DoLayout();
|
||||
}
|
||||
}
|
||||
|
@ -187,13 +187,13 @@ namespace Greenshot.Drawing {
|
|||
|
||||
public Point Location {
|
||||
get {
|
||||
return new Point(left, top);
|
||||
return new Point(_left, _top);
|
||||
}
|
||||
}
|
||||
|
||||
public Size Size {
|
||||
get {
|
||||
return new Size(width, height);
|
||||
return new Size(_width, _height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,13 +201,13 @@ namespace Greenshot.Drawing {
|
|||
/// <summary>
|
||||
/// will store current bounds of this DrawableContainer before starting a resize
|
||||
/// </summary>
|
||||
private Rectangle boundsBeforeResize = Rectangle.Empty;
|
||||
private Rectangle _boundsBeforeResize = Rectangle.Empty;
|
||||
|
||||
[NonSerialized]
|
||||
/// <summary>
|
||||
/// "workbench" rectangle - used for calculatoing bounds during resizing (to be applied to this DrawableContainer afterwards)
|
||||
/// </summary>
|
||||
private RectangleF boundsAfterResize = RectangleF.Empty;
|
||||
private RectangleF _boundsAfterResize = RectangleF.Empty;
|
||||
|
||||
public Rectangle Bounds {
|
||||
get { return GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); }
|
||||
|
@ -417,17 +417,25 @@ namespace Greenshot.Drawing {
|
|||
private void gripperMouseDown(object sender, MouseEventArgs e) {
|
||||
mx = e.X;
|
||||
my = e.Y;
|
||||
Status = EditStatus.RESIZING;
|
||||
boundsBeforeResize = new Rectangle(left, top, width, height);
|
||||
boundsAfterResize = new RectangleF(boundsBeforeResize.Left, boundsBeforeResize.Top, boundsBeforeResize.Width, boundsBeforeResize.Height);
|
||||
isMadeUndoable = false;
|
||||
Gripper originatingGripper = (Gripper)sender;
|
||||
if (originatingGripper != _targetGripper) {
|
||||
Status = EditStatus.RESIZING;
|
||||
_boundsBeforeResize = new Rectangle(_left, _top, _width, _height);
|
||||
_boundsAfterResize = new RectangleF(_boundsBeforeResize.Left, _boundsBeforeResize.Top, _boundsBeforeResize.Width, _boundsBeforeResize.Height);
|
||||
} else {
|
||||
Status = EditStatus.MOVING;
|
||||
}
|
||||
_isMadeUndoable = false;
|
||||
}
|
||||
|
||||
private void gripperMouseUp(object sender, MouseEventArgs e) {
|
||||
Gripper originatingGripper = (Gripper)sender;
|
||||
if (originatingGripper != _targetGripper) {
|
||||
_boundsBeforeResize = Rectangle.Empty;
|
||||
_boundsAfterResize = RectangleF.Empty;
|
||||
_isMadeUndoable = false;
|
||||
}
|
||||
Status = EditStatus.IDLE;
|
||||
boundsBeforeResize = Rectangle.Empty;
|
||||
boundsAfterResize = RectangleF.Empty;
|
||||
isMadeUndoable = false;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
@ -439,9 +447,9 @@ namespace Greenshot.Drawing {
|
|||
TargetGripperMove(absX, absY);
|
||||
} else if (Status.Equals(EditStatus.RESIZING)) {
|
||||
// check if we already made this undoable
|
||||
if (!isMadeUndoable) {
|
||||
if (!_isMadeUndoable) {
|
||||
// don't allow another undo until we are finished with this move
|
||||
isMadeUndoable = true;
|
||||
_isMadeUndoable = true;
|
||||
// Make undo-able
|
||||
MakeBoundsChangeUndoable(false);
|
||||
}
|
||||
|
@ -450,16 +458,16 @@ namespace Greenshot.Drawing {
|
|||
SuspendLayout();
|
||||
|
||||
// reset "workbench" rectangle to current bounds
|
||||
boundsAfterResize.X = boundsBeforeResize.X;
|
||||
boundsAfterResize.Y = boundsBeforeResize.Y;
|
||||
boundsAfterResize.Width = boundsBeforeResize.Width;
|
||||
boundsAfterResize.Height = boundsBeforeResize.Height;
|
||||
_boundsAfterResize.X = _boundsBeforeResize.X;
|
||||
_boundsAfterResize.Y = _boundsBeforeResize.Y;
|
||||
_boundsAfterResize.Width = _boundsBeforeResize.Width;
|
||||
_boundsAfterResize.Height = _boundsBeforeResize.Height;
|
||||
|
||||
// calculate scaled rectangle
|
||||
ScaleHelper.Scale(ref boundsAfterResize, originatingGripper.Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions());
|
||||
ScaleHelper.Scale(ref _boundsAfterResize, originatingGripper.Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions());
|
||||
|
||||
// apply scaled bounds to this DrawableContainer
|
||||
ApplyBounds(boundsAfterResize);
|
||||
ApplyBounds(_boundsAfterResize);
|
||||
|
||||
ResumeLayout();
|
||||
Invalidate();
|
||||
|
@ -541,6 +549,13 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (_targetGripper != null) {
|
||||
if (_targetGripper.Enabled) {
|
||||
_targetGripper.Show();
|
||||
} else {
|
||||
_targetGripper.Hide();
|
||||
}
|
||||
}
|
||||
ResumeLayout();
|
||||
}
|
||||
|
||||
|
@ -551,6 +566,9 @@ namespace Greenshot.Drawing {
|
|||
_grippers[i].Hide();
|
||||
}
|
||||
}
|
||||
if (_targetGripper != null) {
|
||||
_targetGripper.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public void ResizeTo(int width, int height, int anchorPosition) {
|
||||
|
@ -582,8 +600,8 @@ namespace Greenshot.Drawing {
|
|||
/// <param name="y">current mouse y</param>
|
||||
/// <returns>true if the event is handled, false if the surface needs to handle it</returns>
|
||||
public virtual bool HandleMouseDown(int x, int y) {
|
||||
Left = boundsBeforeResize.X = x;
|
||||
Top = boundsBeforeResize.Y = y;
|
||||
Left = _boundsBeforeResize.X = x;
|
||||
Top = _boundsBeforeResize.Y = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -598,15 +616,15 @@ namespace Greenshot.Drawing {
|
|||
SuspendLayout();
|
||||
|
||||
// reset "workrbench" rectangle to current bounds
|
||||
boundsAfterResize.X = boundsBeforeResize.Left;
|
||||
boundsAfterResize.Y = boundsBeforeResize.Top;
|
||||
boundsAfterResize.Width = x - boundsAfterResize.Left;
|
||||
boundsAfterResize.Height = y - boundsAfterResize.Top;
|
||||
_boundsAfterResize.X = _boundsBeforeResize.Left;
|
||||
_boundsAfterResize.Y = _boundsBeforeResize.Top;
|
||||
_boundsAfterResize.Width = x - _boundsAfterResize.Left;
|
||||
_boundsAfterResize.Height = y - _boundsAfterResize.Top;
|
||||
|
||||
ScaleHelper.Scale(boundsBeforeResize, x, y, ref boundsAfterResize, GetAngleRoundProcessor());
|
||||
ScaleHelper.Scale(_boundsBeforeResize, x, y, ref _boundsAfterResize, GetAngleRoundProcessor());
|
||||
|
||||
// apply scaled bounds to this DrawableContainer
|
||||
ApplyBounds(boundsAfterResize);
|
||||
ApplyBounds(_boundsAfterResize);
|
||||
|
||||
ResumeLayout();
|
||||
Invalidate();
|
||||
|
@ -641,7 +659,7 @@ namespace Greenshot.Drawing {
|
|||
bool ret = false;
|
||||
if (obj != null && GetType().Equals(obj.GetType())) {
|
||||
DrawableContainer other = obj as DrawableContainer;
|
||||
if (left==other.left && top==other.top && width==other.width && height==other.height) {
|
||||
if (_left==other._left && _top==other._top && _width==other._width && _height==other._height) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
@ -649,7 +667,7 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
public override int GetHashCode() {
|
||||
return left.GetHashCode() ^ top.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ GetFields().GetHashCode();
|
||||
return _left.GetHashCode() ^ _top.GetHashCode() ^ _width.GetHashCode() ^ _height.GetHashCode() ^ GetFields().GetHashCode();
|
||||
}
|
||||
|
||||
protected void OnPropertyChanged(string propertyName) {
|
||||
|
|
|
@ -52,6 +52,18 @@ namespace Greenshot.Drawing {
|
|||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
DrawEllipse(rect, graphics, renderMode, lineThickness, lineColor, fillColor, shadow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This allows another container to draw an ellipse
|
||||
/// </summary>
|
||||
/// <param name="caller"></param>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="renderMode"></param>
|
||||
public static void DrawEllipse(Rectangle rect, Graphics graphics, RenderMode renderMode, int lineThickness, Color lineColor, Color fillColor, bool shadow) {
|
||||
|
||||
bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor));
|
||||
// draw shadow before anything else
|
||||
if (shadow && (lineVisible || Colors.IsVisible(fillColor))) {
|
||||
|
@ -62,7 +74,7 @@ namespace Greenshot.Drawing {
|
|||
while (currentStep <= steps) {
|
||||
using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) {
|
||||
shadowPen.Width = lineVisible ? lineThickness : 1;
|
||||
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + currentStep, Top + currentStep, Width, Height);
|
||||
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(rect.Left + currentStep, rect.Top + currentStep, rect.Width, rect.Height);
|
||||
graphics.DrawEllipse(shadowPen, shadowRect);
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
|
@ -70,7 +82,6 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
}
|
||||
//draw the original shape
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
if (Colors.IsVisible(fillColor)) {
|
||||
using (Brush brush = new SolidBrush(fillColor)) {
|
||||
graphics.FillEllipse(brush, rect);
|
||||
|
@ -84,20 +95,35 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
public override bool Contains(int x, int y) {
|
||||
double xDistanceFromCenter = x - (Left+Width/2);
|
||||
double yDistanceFromCenter = y - (Top+Height/2);
|
||||
// ellipse: x^2/a^2 + y^2/b^2 = 1
|
||||
return Math.Pow(xDistanceFromCenter,2)/Math.Pow(Width/2,2) + Math.Pow(yDistanceFromCenter,2)/Math.Pow(Height/2,2) < 1;
|
||||
return EllipseContains(this, x, y);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Allow the code to be used externally
|
||||
/// </summary>
|
||||
/// <param name="caller"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool EllipseContains(DrawableContainer caller, int x, int y) {
|
||||
double xDistanceFromCenter = x - (caller.Left + caller.Width / 2);
|
||||
double yDistanceFromCenter = y - (caller.Top + caller.Height / 2);
|
||||
// ellipse: x^2/a^2 + y^2/b^2 = 1
|
||||
return Math.Pow(xDistanceFromCenter, 2) / Math.Pow(caller.Width / 2, 2) + Math.Pow(yDistanceFromCenter, 2) / Math.Pow(caller.Height / 2, 2) < 1;
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y) {
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
return EllipseClickableAt(rect, lineThickness, fillColor, x, y);
|
||||
}
|
||||
|
||||
public static bool EllipseClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y) {
|
||||
// If we clicked inside the rectangle and it's visible we are clickable at.
|
||||
if (!Color.Transparent.Equals(fillColor)) {
|
||||
if (Contains(x,y)) {
|
||||
if (rect.Contains(x, y)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ namespace Greenshot.Drawing {
|
|||
/// <summary>
|
||||
/// Represents a rectangular shape on the Surface
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class RectangleContainer : DrawableContainer {
|
||||
private static readonly ILog LOG = LogManager.GetLogger(typeof(RectangleContainer));
|
||||
|
||||
|
@ -45,15 +45,31 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
DrawRectangle(rect, graphics, rm, lineThickness, lineColor, fillColor, shadow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can also be used from other containers, if the right values are passed!
|
||||
/// </summary>
|
||||
/// <param name="rect"></param>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="rm"></param>
|
||||
/// <param name="lineThickness"></param>
|
||||
/// <param name="lineColor"></param>
|
||||
/// <param name="fillColor"></param>
|
||||
/// <param name="shadow"></param>
|
||||
public static void DrawRectangle(Rectangle rect, Graphics graphics, RenderMode rm, int lineThickness, Color lineColor, Color fillColor, bool shadow) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor));
|
||||
if (shadow && (lineVisible || Colors.IsVisible(fillColor))) {
|
||||
//draw shadow first
|
||||
|
@ -65,18 +81,17 @@ namespace Greenshot.Drawing {
|
|||
using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100))) {
|
||||
shadowPen.Width = lineVisible ? lineThickness : 1;
|
||||
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(
|
||||
Left + currentStep,
|
||||
Top + currentStep,
|
||||
Width,
|
||||
Height);
|
||||
rect.Left + currentStep,
|
||||
rect.Top + currentStep,
|
||||
rect.Width,
|
||||
rect.Height);
|
||||
graphics.DrawRectangle(shadowPen, shadowRect);
|
||||
currentStep++;
|
||||
alpha = alpha - (basealpha / steps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
|
||||
if (Colors.IsVisible(fillColor)) {
|
||||
using (Brush brush = new SolidBrush(fillColor)) {
|
||||
|
@ -90,13 +105,19 @@ namespace Greenshot.Drawing {
|
|||
graphics.DrawRectangle(pen, rect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y) {
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
|
||||
return RectangleClickableAt(rect, lineThickness, fillColor, x, y);
|
||||
}
|
||||
|
||||
|
||||
public static bool RectangleClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y) {
|
||||
|
||||
// If we clicked inside the rectangle and it's visible we are clickable at.
|
||||
if (!Color.Transparent.Equals(fillColor)) {
|
||||
if (rect.Contains(x,y)) {
|
||||
|
|
|
@ -42,12 +42,12 @@ namespace Greenshot.Drawing {
|
|||
/// We set our own field values
|
||||
/// </summary>
|
||||
protected override void InitializeFields() {
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 4);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, Color.Blue);
|
||||
AddField(GetType(), FieldType.SHADOW, true);
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 0);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, Color.White);
|
||||
AddField(GetType(), FieldType.SHADOW, false);
|
||||
AddField(GetType(), FieldType.FONT_ITALIC, false);
|
||||
AddField(GetType(), FieldType.FONT_BOLD, false);
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
|
||||
AddField(GetType(), FieldType.FONT_BOLD, true);
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.LightBlue);
|
||||
AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
|
||||
AddField(GetType(), FieldType.FONT_SIZE, 20f);
|
||||
AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, HorizontalAlignment.Center);
|
||||
|
@ -58,6 +58,7 @@ namespace Greenshot.Drawing {
|
|||
base.TargetGripperMove(absX, absY);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from Surface (the _parent) when the drawing begins (mouse-down)
|
||||
/// </summary>
|
||||
|
@ -156,15 +157,15 @@ namespace Greenshot.Drawing {
|
|||
graphics.Restore(state);
|
||||
}
|
||||
|
||||
// Draw the text
|
||||
StringFormat format = new StringFormat();
|
||||
format.Alignment = StringAlignment.Center;
|
||||
format.LineAlignment = StringAlignment.Center;
|
||||
DrawText(graphics, GuiRectangle.GetGuiRectangle(Left, Top, Width, Height), format);
|
||||
|
||||
// cleanup
|
||||
// cleanup the paths
|
||||
bubble.Dispose();
|
||||
tail.Dispose();
|
||||
|
||||
// Draw the text
|
||||
UpdateFormat();
|
||||
DrawText(graphics, rect, lineThickness, lineColor, false, StringFormat, Text, Font);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public override bool Contains(int x, int y) {
|
||||
|
|
|
@ -33,32 +33,50 @@ namespace Greenshot.Drawing {
|
|||
/// This is an enumerated label, every single StepLabelContainer shows the number of the order it was created.
|
||||
/// To make sure that deleting recalculates, we check the location before every draw.
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
public class StepLabelContainer : TextContainer {
|
||||
[Serializable]
|
||||
public class StepLabelContainer : DrawableContainer {
|
||||
[NonSerialized]
|
||||
private StringFormat _stringFormat = new StringFormat();
|
||||
[NonSerialized]
|
||||
private Font _font;
|
||||
private bool drawAsRectangle = false;
|
||||
|
||||
public StepLabelContainer(Surface parent) : base(parent) {
|
||||
_defaultEditMode = EditStatus.IDLE;
|
||||
parent.StepContainers.AddLast(this);
|
||||
InitContent();
|
||||
}
|
||||
|
||||
public override bool InitContent() {
|
||||
_defaultEditMode = EditStatus.IDLE;
|
||||
_stringFormat.Alignment = StringAlignment.Center;
|
||||
_stringFormat.LineAlignment = StringAlignment.Center;
|
||||
|
||||
// Set defaults
|
||||
Width = 40;
|
||||
Height = 40;
|
||||
}
|
||||
|
||||
public override void Dispose() {
|
||||
Parent.StepContainers.Remove(this);
|
||||
base.Dispose();
|
||||
using (FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name)) {
|
||||
_font = new Font(fam, 18, FontStyle.Regular, GraphicsUnit.Pixel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We set our own field values
|
||||
/// </summary>
|
||||
protected override void InitializeFields() {
|
||||
AddField(GetType(), FieldType.LINE_COLOR, Color.White);
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.DarkRed);
|
||||
AddField(GetType(), FieldType.FONT_SIZE, 21f);
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 0);
|
||||
base.InitializeFields();
|
||||
AddField(GetType(), FieldType.LINE_COLOR, Color.White);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure this element is no longer referenced from the surface
|
||||
/// </summary>
|
||||
public override void Dispose() {
|
||||
Parent.StepContainers.Remove(this);
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Override the parent, calculate the label number, than draw
|
||||
/// </summary>
|
||||
|
@ -74,8 +92,26 @@ namespace Greenshot.Drawing {
|
|||
number++;
|
||||
}
|
||||
}
|
||||
this.Text = number.ToString();
|
||||
base.Draw(graphics, rm);
|
||||
string text = number.ToString();
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
if (drawAsRectangle) {
|
||||
RectangleContainer.DrawRectangle(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
|
||||
} else {
|
||||
EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
|
||||
}
|
||||
TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, _font);
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y) {
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
if (drawAsRectangle) {
|
||||
return RectangleContainer.RectangleClickableAt(rect, 0, fillColor, x, y);
|
||||
} else {
|
||||
return EllipseContainer.EllipseClickableAt(rect, 0, fillColor, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,13 +43,21 @@ namespace Greenshot.Drawing {
|
|||
// This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack
|
||||
private bool makeUndoable;
|
||||
private Font _font;
|
||||
|
||||
public Font Font {
|
||||
get {
|
||||
return _font;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The StringFormat object is not serializable!!
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
StringFormat stringFormat = new StringFormat();
|
||||
|
||||
StringFormat _stringFormat = new StringFormat();
|
||||
public StringFormat StringFormat {
|
||||
get {
|
||||
return _stringFormat;
|
||||
}
|
||||
}
|
||||
private string _text;
|
||||
// there is a binding on the following property!
|
||||
public string Text {
|
||||
|
@ -75,8 +83,8 @@ namespace Greenshot.Drawing {
|
|||
|
||||
public TextContainer(Surface parent) : base(parent) {
|
||||
Init();
|
||||
stringFormat = new StringFormat();
|
||||
stringFormat.Trimming = StringTrimming.EllipsisWord;
|
||||
_stringFormat = new StringFormat();
|
||||
_stringFormat.Trimming = StringTrimming.EllipsisWord;
|
||||
}
|
||||
|
||||
protected override void InitializeFields() {
|
||||
|
@ -94,7 +102,7 @@ namespace Greenshot.Drawing {
|
|||
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context) {
|
||||
stringFormat = new StringFormat();
|
||||
_stringFormat = new StringFormat();
|
||||
Init();
|
||||
UpdateFormat();
|
||||
}
|
||||
|
@ -105,9 +113,9 @@ namespace Greenshot.Drawing {
|
|||
_font.Dispose();
|
||||
_font = null;
|
||||
}
|
||||
if (stringFormat != null) {
|
||||
stringFormat.Dispose();
|
||||
stringFormat = null;
|
||||
if (_stringFormat != null) {
|
||||
_stringFormat.Dispose();
|
||||
_stringFormat = null;
|
||||
}
|
||||
if (textBox != null) {
|
||||
textBox.Dispose();
|
||||
|
@ -205,7 +213,7 @@ namespace Greenshot.Drawing {
|
|||
_parent.Controls.Remove(textBox);
|
||||
}
|
||||
|
||||
private void UpdateFormat() {
|
||||
protected void UpdateFormat() {
|
||||
string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY);
|
||||
bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD);
|
||||
bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC);
|
||||
|
@ -252,8 +260,8 @@ namespace Greenshot.Drawing {
|
|||
throw;
|
||||
}
|
||||
|
||||
stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
|
||||
stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
|
||||
_stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
|
||||
_stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
|
||||
}
|
||||
|
||||
private void UpdateTextBoxPosition() {
|
||||
|
@ -311,47 +319,53 @@ namespace Greenshot.Drawing {
|
|||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
int textOffset = (lineThickness>0) ? (int)Math.Ceiling(lineThickness/2d) : 0;
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty);
|
||||
|
||||
DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, _text, _font);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can be used from other containers
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="drawingRectange"></param>
|
||||
/// <param name="lineThickness"></param>
|
||||
/// <param name="fontColor"></param>
|
||||
/// <param name="stringFormat"></param>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="font"></param>
|
||||
public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font) {
|
||||
int textOffset = (lineThickness > 0) ? (int)Math.Ceiling(lineThickness / 2d) : 0;
|
||||
// draw shadow before anything else
|
||||
if (shadow && (fillColor == Color.Transparent || fillColor == Color.Empty)) {
|
||||
if (drawShadow) {
|
||||
int basealpha = 100;
|
||||
int alpha = basealpha;
|
||||
int steps = 5;
|
||||
int currentStep = 1;
|
||||
while (currentStep <= steps) {
|
||||
int offset = currentStep;
|
||||
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + offset, Top + offset, Width, Height);
|
||||
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height);
|
||||
if (lineThickness > 0) {
|
||||
shadowRect.Inflate(-textOffset, -textOffset);
|
||||
}
|
||||
using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) {
|
||||
graphics.DrawString(_text, _font, fontBrush, shadowRect, stringFormat);
|
||||
graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat);
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
DrawText(graphics, rect, null);
|
||||
}
|
||||
|
||||
protected void DrawText(Graphics graphics, Rectangle drawingRectange, StringFormat stringFormat) {
|
||||
UpdateFormat();
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Rectangle fontRect = drawingRectange;
|
||||
int textOffset = (lineThickness > 0) ? (int)Math.Ceiling(lineThickness / 2d) : 0;
|
||||
if (lineThickness > 0) {
|
||||
graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
||||
fontRect.Inflate(-textOffset, -textOffset);
|
||||
drawingRectange.Inflate(-textOffset, -textOffset);
|
||||
}
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
using (Brush fontBrush = new SolidBrush(lineColor)) {
|
||||
graphics.DrawString(_text, _font, fontBrush, fontRect);
|
||||
using (Brush fontBrush = new SolidBrush(fontColor)) {
|
||||
if (stringFormat != null) {
|
||||
graphics.DrawString(_text, _font, fontBrush, fontRect, stringFormat);
|
||||
graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat);
|
||||
} else {
|
||||
graphics.DrawString(_text, _font, fontBrush, fontRect);
|
||||
graphics.DrawString(text, font, fontBrush, drawingRectange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue