/*
* 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