/* * 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 . */ 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 { /// /// 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. /// [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 filters = new List(); public List Filters { get { List ret = new List(); 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[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= 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