mirror of
https://github.com/greenshot/greenshot
synced 2025-07-10 23:33:33 -07:00
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@704 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
402 lines
No EOL
12 KiB
C#
402 lines
No EOL
12 KiB
C#
/*
|
|
* Greenshot - a free and open source screenshot tool
|
|
* Copyright (C) 2007-2010 Thomas Braun, Jens Klingen, Robin Krom
|
|
*
|
|
* For more information see: http://getgreenshot.org/
|
|
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 1 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Drawing.Drawing2D;
|
|
using System.Drawing.Imaging;
|
|
using System.Runtime.Serialization;
|
|
using System.Windows.Forms;
|
|
|
|
using Greenshot.Configuration;
|
|
using Greenshot.Controls;
|
|
using Greenshot.Drawing.Fields;
|
|
using Greenshot.Drawing.Filters;
|
|
using Greenshot.Helpers;
|
|
using Greenshot.Plugin;
|
|
|
|
namespace Greenshot.Drawing {
|
|
/// <summary>
|
|
/// represents a rectangle, ellipse, label or whatever. Can contain filters, too.
|
|
/// serializable for clipboard support
|
|
/// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call
|
|
/// OnPropertyChanged whenever a public property has been changed.
|
|
/// </summary>
|
|
[Serializable()]
|
|
public abstract class DrawableContainer : AbstractFieldHolderWithChildren, INotifyPropertyChanged, IDrawableContainer {
|
|
|
|
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(DrawableContainer));
|
|
|
|
[NonSerialized]
|
|
private PropertyChangedEventHandler propertyChanged;
|
|
public event PropertyChangedEventHandler PropertyChanged {
|
|
add { propertyChanged += value; }
|
|
remove{ propertyChanged -= value; }
|
|
}
|
|
|
|
|
|
|
|
// public List<IFilter> filters = new List<IFilter>();
|
|
public List<IFilter> Filters {
|
|
get {
|
|
List<IFilter> ret = new List<IFilter>();
|
|
foreach(IFieldHolder c in Children) {
|
|
if(c is IFilter) ret.Add(c as IFilter);
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
[NonSerialized]
|
|
protected Surface parent;
|
|
public ISurface Parent {
|
|
get { return parent; }
|
|
set { SwitchParent((Surface)value); }
|
|
}
|
|
[NonSerialized]
|
|
protected Label[] grippers;
|
|
private bool layoutSuspended = false;
|
|
[NonSerialized]
|
|
protected Label childLabel;
|
|
|
|
[NonSerialized]
|
|
private bool selected = false;
|
|
public bool Selected {
|
|
get {return selected;}
|
|
set {selected = value; OnPropertyChanged("Selected"); }
|
|
}
|
|
|
|
[NonSerialized]
|
|
public EditStatus Status = EditStatus.UNDRAWN;
|
|
|
|
private int left = 0;
|
|
public int Left {
|
|
get { return left; }
|
|
set { left = value; DoLayout(); OnPropertyChanged("Left"); }
|
|
}
|
|
|
|
private int top = 0;
|
|
public int Top {
|
|
get { return top; }
|
|
set { top = value; DoLayout(); OnPropertyChanged("Top"); }
|
|
}
|
|
|
|
private int width = 0;
|
|
public int Width {
|
|
get { return width; }
|
|
set { width = value; DoLayout(); OnPropertyChanged("Width"); }
|
|
}
|
|
|
|
private int height = 0;
|
|
public int Height {
|
|
get { return height; }
|
|
set { height = value; DoLayout(); OnPropertyChanged("Height"); }
|
|
}
|
|
|
|
public Rectangle Bounds {
|
|
get { return GuiRectangle.GetGuiRectangle(left, top, width, height); }
|
|
}
|
|
|
|
public DrawableContainer(Surface parent) {
|
|
this.parent = parent;
|
|
InitControls();
|
|
}
|
|
|
|
public void Add(IFilter filter) {
|
|
AddChild(filter);
|
|
}
|
|
|
|
public void Remove(IFilter filter) {
|
|
RemoveChild(filter);
|
|
}
|
|
|
|
public Label GetLabel() {
|
|
return childLabel;
|
|
}
|
|
|
|
public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) {
|
|
|
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
|
if (horizontalAlignment == HorizontalAlignment.Left) {
|
|
Left = lineThickness/2;
|
|
}
|
|
if (horizontalAlignment == HorizontalAlignment.Right) {
|
|
Left = parent.Width - this.Width - lineThickness/2;
|
|
}
|
|
if (horizontalAlignment == HorizontalAlignment.Center) {
|
|
Left = (parent.Width / 2) - (this.Width / 2) - lineThickness/2;
|
|
}
|
|
|
|
if (verticalAlignment == VerticalAlignment.TOP) {
|
|
Top = lineThickness/2;
|
|
}
|
|
if (verticalAlignment == VerticalAlignment.BOTTOM) {
|
|
Top = parent.Height - this.Height - lineThickness/2;
|
|
}
|
|
if (verticalAlignment == VerticalAlignment.CENTER) {
|
|
Top = (parent.Height / 2) - (this.Height / 2) - lineThickness/2;
|
|
}
|
|
}
|
|
|
|
public virtual bool InitContent() { return true; }
|
|
|
|
public virtual void OnDoubleClick() {}
|
|
|
|
private void InitControls() {
|
|
InitGrippers();
|
|
childLabel = new Label();
|
|
childLabel.BackColor = Color.Transparent;
|
|
childLabel.BorderStyle = BorderStyle.None;
|
|
childLabel.Cursor = Cursors.SizeAll;
|
|
childLabel.MouseDown += new MouseEventHandler(gripperMouseDown);
|
|
childLabel.MouseUp += new MouseEventHandler(gripperMouseUp);
|
|
childLabel.MouseMove += new MouseEventHandler(childLabelMouseMove);
|
|
|
|
DoLayout();
|
|
}
|
|
|
|
void InitGrippers() {
|
|
grippers = new Label[8];
|
|
for(int i=0; i<grippers.Length; i++) {
|
|
grippers[i] = new Label();
|
|
grippers[i].Name = "gripper" + i;
|
|
grippers[i].Width = grippers[i].Height = 5;
|
|
grippers[i].BackColor = Color.Black;
|
|
grippers[i].MouseDown += new MouseEventHandler(gripperMouseDown);
|
|
grippers[i].MouseUp += new MouseEventHandler(gripperMouseUp);
|
|
grippers[i].MouseMove += new MouseEventHandler(gripperMouseMove);
|
|
grippers[i].Visible = false;
|
|
}
|
|
grippers[1].Cursor = Cursors.SizeNS;
|
|
grippers[3].Cursor = Cursors.SizeWE;
|
|
grippers[5].Cursor = Cursors.SizeNS;
|
|
grippers[7].Cursor = Cursors.SizeWE;
|
|
if(parent != null) parent.Controls.AddRange(grippers); // otherwise we'll attach them in switchParent
|
|
}
|
|
|
|
public void SuspendLayout() {
|
|
layoutSuspended = true;
|
|
childLabel.SuspendLayout();
|
|
}
|
|
|
|
public void ResumeLayout() {
|
|
layoutSuspended = false;
|
|
DoLayout();
|
|
childLabel.ResumeLayout();
|
|
}
|
|
|
|
private void DoLayout() {
|
|
if (!layoutSuspended) {
|
|
int[] xChoords = new int[]{this.Left-2,this.Left+this.Width/2-2,this.Left+this.Width-2};
|
|
int[] yChoords = new int[]{this.Top-2,this.Top+this.Height/2-2,this.Top+this.Height-2};
|
|
|
|
grippers[0].Left = xChoords[0]; grippers[0].Top = yChoords[0];
|
|
grippers[1].Left = xChoords[1]; grippers[1].Top = yChoords[0];
|
|
grippers[2].Left = xChoords[2]; grippers[2].Top = yChoords[0];
|
|
grippers[3].Left = xChoords[2]; grippers[3].Top = yChoords[1];
|
|
grippers[4].Left = xChoords[2]; grippers[4].Top = yChoords[2];
|
|
grippers[5].Left = xChoords[1]; grippers[5].Top = yChoords[2];
|
|
grippers[6].Left = xChoords[0]; grippers[6].Top = yChoords[2];
|
|
grippers[7].Left = xChoords[0]; grippers[7].Top = yChoords[1];
|
|
|
|
if((grippers[0].Left < grippers[4].Left && grippers[0].Top < grippers[4].Top) ||
|
|
grippers[0].Left > grippers[4].Left && grippers[0].Top > grippers[4].Top) {
|
|
grippers[0].Cursor = Cursors.SizeNWSE;
|
|
grippers[2].Cursor = Cursors.SizeNESW;
|
|
grippers[4].Cursor = Cursors.SizeNWSE;
|
|
grippers[6].Cursor = Cursors.SizeNESW;
|
|
} else if((grippers[0].Left > grippers[4].Left && grippers[0].Top < grippers[4].Top) ||
|
|
grippers[0].Left < grippers[4].Left && grippers[0].Top > grippers[4].Top) {
|
|
grippers[0].Cursor = Cursors.SizeNESW;
|
|
grippers[2].Cursor = Cursors.SizeNWSE;
|
|
grippers[4].Cursor = Cursors.SizeNESW;
|
|
grippers[6].Cursor = Cursors.SizeNWSE;
|
|
} else if (grippers[0].Left == grippers[4].Left) {
|
|
grippers[0].Cursor = Cursors.SizeNS;
|
|
grippers[4].Cursor = Cursors.SizeNS;
|
|
} else if (grippers[0].Top == grippers[4].Top) {
|
|
grippers[0].Cursor = Cursors.SizeWE;
|
|
grippers[4].Cursor = Cursors.SizeWE;
|
|
}
|
|
|
|
childLabel.Left = this.Left;
|
|
childLabel.Top = this.Top;
|
|
childLabel.Width = this.Width;
|
|
childLabel.Height = this.Height;
|
|
}
|
|
}
|
|
|
|
public virtual void Dispose() {
|
|
for(int i=0; i<grippers.Length; i++) {
|
|
grippers[i].Dispose();
|
|
}
|
|
childLabel.Dispose();
|
|
|
|
FieldAggregator aggProps = parent.FieldAggregator;
|
|
aggProps.UnbindElement(this);
|
|
|
|
|
|
}
|
|
|
|
int mx;
|
|
int my;
|
|
private void gripperMouseDown(object sender, MouseEventArgs e) {
|
|
mx = e.X;
|
|
my = e.Y;
|
|
Status = EditStatus.RESIZING;
|
|
parent.Invalidate();
|
|
}
|
|
|
|
private void gripperMouseUp(object sender, MouseEventArgs e) {
|
|
Status = EditStatus.IDLE;
|
|
parent.Invalidate();
|
|
}
|
|
|
|
private void gripperMouseMove(object sender, MouseEventArgs e) {
|
|
if(Status.Equals(EditStatus.RESIZING)) {
|
|
SuspendLayout();
|
|
Label gr = (Label)sender;
|
|
int gripperIndex = Int16.Parse(gr.Name.Substring(7));
|
|
if(gripperIndex <= 2) { // top row
|
|
this.Top += e.Y - my;
|
|
this.Height -= e.Y - my;
|
|
} else if(gripperIndex >= 4 && gripperIndex <= 6) { // bottom row
|
|
this.Height += e.Y - my;
|
|
}
|
|
if(gripperIndex >=2 && gripperIndex <= 4) { // right row
|
|
this.Width += e.X - mx;
|
|
} else if(gripperIndex >=6 || gripperIndex == 0) { // left row
|
|
this.Left += e.X - mx;
|
|
this.Width -= e.X - mx;
|
|
}
|
|
ResumeLayout();
|
|
parent.Invalidate();
|
|
}
|
|
}
|
|
|
|
private void childLabelMouseMove(object sender, MouseEventArgs e) {
|
|
if (Status.Equals(EditStatus.RESIZING)) {
|
|
SuspendLayout();
|
|
this.Left += e.X - mx;
|
|
this.Top += e.Y - my;
|
|
ResumeLayout();
|
|
parent.Invalidate();
|
|
}
|
|
}
|
|
|
|
public abstract void Draw(Graphics graphics, RenderMode renderMode);
|
|
|
|
public virtual void DrawContent(Graphics graphics, Bitmap bmp, RenderMode renderMode) {
|
|
//if(LOG.IsDebugEnabled) LOG.Debug("Drawing container "+this+" with bounds "+Bounds+" and " + Children.Count + " children and status: "+Status);
|
|
if(Children.Count>0) {
|
|
if(!Status.Equals(EditStatus.IDLE)) {
|
|
DrawSelectionBorder(graphics, Bounds);
|
|
} else {
|
|
Rectangle effRect = Bounds;
|
|
|
|
if(!effRect.IsEmpty) {
|
|
foreach(IFilter filter in Filters) {
|
|
//if(LOG.IsDebugEnabled) LOG.Debug("Applying filter "+filter+" with bounds "+effRect);
|
|
filter.Apply(graphics, bmp, effRect, renderMode);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
Draw(graphics, RenderMode.EDIT);
|
|
}
|
|
|
|
public virtual bool Contains(int x, int y) {
|
|
return Bounds.Contains(x,y);
|
|
}
|
|
|
|
public virtual bool ClickableAt(int x, int y) {
|
|
Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
|
r.Inflate(5, 5);
|
|
return r.Contains(x, y);
|
|
}
|
|
|
|
protected void DrawSelectionBorder(Graphics g, Rectangle rect) {
|
|
using (Pen pen = new Pen(Color.MediumSeaGreen)) {
|
|
pen.DashPattern = new float[]{1,2};
|
|
pen.Width = 1;
|
|
g.DrawRectangle(pen, rect);
|
|
}
|
|
}
|
|
|
|
public void ShowGrippers() {
|
|
for(int i=0; i<grippers.Length; i++) {
|
|
if(grippers[i].Enabled) grippers[i].Show();
|
|
else grippers[i].Hide();
|
|
}
|
|
this.ResumeLayout();
|
|
}
|
|
|
|
public void HideGrippers() {
|
|
this.SuspendLayout();
|
|
for(int i=0; i<grippers.Length; i++) {
|
|
grippers[i].Hide();
|
|
}
|
|
}
|
|
|
|
public void MoveBy(int dx, int dy) {
|
|
this.SuspendLayout();
|
|
this.Left += dx;
|
|
this.Top += dy;
|
|
this.ResumeLayout();
|
|
}
|
|
|
|
private void SwitchParent(Surface newParent) {
|
|
if(parent != null) {
|
|
for(int i=0; i<grippers.Length; i++) {
|
|
parent.Controls.Remove(grippers[i]);
|
|
}
|
|
} else if(grippers == null) {
|
|
InitControls();
|
|
}
|
|
parent = newParent;
|
|
parent.Controls.AddRange(grippers);
|
|
foreach(IFilter filter in Filters) {
|
|
filter.Parent = this;
|
|
}
|
|
}
|
|
|
|
// drawablecontainers are regarded equal if they are of the same type and their bounds are equal. this should be sufficient.
|
|
public override bool Equals(object obj) {
|
|
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) ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
public override int GetHashCode() {
|
|
return left.GetHashCode() ^ top.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ GetFields().GetHashCode();
|
|
}
|
|
|
|
protected void OnPropertyChanged(string propertyName) {
|
|
if(propertyChanged != null) propertyChanged(this, new PropertyChangedEventArgs(propertyName));
|
|
}
|
|
}
|
|
} |