|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
/*
* copyright :: Gerard Sławiński
*
* Class created by Gerard Sławiński || turbosqel
*
* version :: 0.9 (test round)
*
*/
namespace TForm.classes.display {
public class RelativeLayout {
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ MAIN DATA
protected static Dictionary<Control, List<Position>> items = new Dictionary<Control, List<Position>>();
protected static List<Position> noAssign = new List<Position>();
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------------------ MANAGE ITEMS
////////////////////////////////////////////////////////////
// <------------------------------ ADD / REMOVE
public static Position Add(Control component) {
Control parent = component.Parent;
component.ParentChanged += NewParent;
Position Pos = new Position(component, parent);
Register(Pos);
return Pos;
}
public static void Remove(Position pos) {
RemovePosition(pos);
}
public static bool Remove(Control child) {
if (child.Parent == null) {
foreach (Position pos in noAssign) {
if (pos.Target == child) {
noAssign.Remove(pos);
pos.internalRemove();
return true;
}
}
} else {
foreach (KeyValuePair<Control, List<Position>> pair in items) {
if (pair.Key == child.Parent) {
Position position = null;
foreach (Position pos in pair.Value) {
if (pos.Target == child) {
position = pos;
break;
}
};
if (position != null) {
RemovePosition(position);
return true;
}
};
}
}
return false;
}
// <------------------------------ INVALIDATE
public static bool ReplaceContainer(Control parent) {
if(items.ContainsKey(parent)){
List<Position> list = items[parent];
foreach (Position pos in list) {
pos.Resize();
}
return true;
}
return false;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
///<summary>
/// remove component and position instance from lists
///</summary>
static void RemovePosition(Position pos) {
if (pos.Parent == null) {
noAssign.Remove(pos);
} else {
items[pos.Parent].Remove(pos);
VerifyParent(pos.Parent);
};
pos.internalRemove();
}
///<summary>
/// remove child Control from parent and remove from list if there is no more children
///</summary>
static void RemoveParent(Control child ,Control parent) {
if (items.ContainsKey(parent)) {
List<Position> parentList = items[parent];
foreach (Position pos in parentList) {
if(pos.Target == child){
parentList.Remove(pos);
break;
}
}
VerifyParent(parent);
}
}
static void VerifyParent(Control parent) {
List<Position> list = items[parent];
if (list != null && list.Count == 0) {
parent.Resize -= ParentResize;
items.Remove(parent);
}
}
static void Register(Position pos) {
if (pos.Parent == null) {
noAssign.Add(pos);
} else {
List<Position> itemsList;
if (items.ContainsKey(pos.Parent)) {
itemsList = items[pos.Parent];
} else {
itemsList = new List<Position>();
items[pos.Parent] = itemsList;
pos.Parent.Resize += ParentResize;
}
itemsList.Add(pos);
}
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ EVENT HANDLERS
///<summary>
/// change item parent
///</summary>
static void NewParent(object sender, EventArgs e) {
Control Current = (Control)sender;
Control newParent = Current.Parent;
Position position = null;
// check if last parent was null:
foreach (Position pos in noAssign) {
if (pos.Target == Current) {
position = pos;
noAssign.Remove(position);
goto AddItem;
}
}
// loop and find sender list
foreach (KeyValuePair<Control, List<Position>> pair in items) {
// focus on list
List<Position> list = pair.Value;
// check for sender Position
foreach (Position pos in list) {
// compare item with target Control
if (pos.Target == Current) {
position = pos;
// remove old reference if exist
// 1. check if parent was null
List<Position> OldList = items.ContainsKey(pos.Parent) ? items[pos.Parent] : null;
if (OldList != null && OldList.Contains(pos)) {
OldList.Remove(pos);
// remove parent if there are no more children
VerifyParent(pos.Parent);
}
// target position instance found
goto AddItem;
}
}
}
return;
AddItem:
// rest::
// set Position new parent
position.Parent = newParent;
// add into index
Register(position);
}
static void ParentResize(object sender, EventArgs e) {
List<Position> list = items[(Control)sender];
foreach (Position pos in list) {
pos.Resize();
}
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ DEBUG
/*
public static void DisplayElements() {
DebugConsole.text = "================= < start > Display elements ::";
foreach (KeyValuePair<Control, List<Position>> pair in items) {
DebugConsole.text = "Parent control ::" + pair.Key.Name + " , elements :" + pair.Value.Count;
foreach(Position pos in pair.Value){
DebugConsole.text = pos.ToString();
}
};
DebugConsole.text = "Unassign elements:";
foreach (Position pos in noAssign) {
DebugConsole.text = pos.ToString();
}
DebugConsole.text = "================= < end >";
}
*/
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
public class Position {
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ STATIC INITIALIZERS
public static bool DefaultAutoResize = true;
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ MAIN PARAMS
public Control Parent;
public Control Target;
public Rectangle Rect = new Rectangle();
public bool AllowResize = DefaultAutoResize;
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ POSITION PARAMS
// <------------- up center down
public float Top = float.NaN;
public float Vertical = float.NaN;
public float Bottom = float.NaN;
///<summary>
/// between 0-1; 0-100% of parent size
///</summary>
public float RelativeVertical = float.NaN;
// <------------- left center right
public float Left = float.NaN;
public float Horizontal = float.NaN;
public float Right = float.NaN;
///<summary>
/// between 0-1; 0-100% of parent size
///</summary>
public float RelativeHorizontal = float.NaN;
// <------------------------------ SIZE PARAMS
// <------------- regular and relative
///<summary>
/// set width or relative width . To set regular width , value must be positive .
/// Relative value should be negative and between 0 and -1 ( 0 - 100% ) , scale of parent size
///</summary>
public float Width = float.NaN;
///<summary>
/// set height or relative height . To set regular height , value must be positive .
/// Relative value should be negative and between 0 and -1 ( 0 - 100% ) , scale of parent size
///</summary>
public float Height = float.NaN;
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ EVENTS
public delegate void ResizeRequestHandler(Position target);
public event ResizeRequestHandler ResizeRequest;
public delegate void ResizedHandler(Position target);
public event ResizedHandler Resized;
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ CTORS
public Position(Control target , Control parent = null) {
Parent = parent;
Target = target;
Rect.x = Target.Left;
Rect.y = Target.Top;
Rect.width = Target.Width;
Rect.height = Target.Height;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ RESIZE
/*
*
private function get horizontalMode():int {
return ((isNaN(_left) ? 0:1) + (isNaN(_horizontal) ? 0:2) + (isNaN(_right) ? 0:4));
};
*
*
*/
/*
*
* 1 top
* 2 vertical
* 3 top + vertical
* 4 bottom
* 5 top + bottom
* 6 vertical + bottom
* 7 top + vertical + bottom
*
*/
protected int horizontalMode() {
return (float.IsNaN(Left) ? 0 : 1) + ((float.IsNaN(Horizontal) && float.IsNaN(RelativeHorizontal)) ? 0 : 2) + (float.IsNaN(Right) ? 0 : 4);
}
protected int verticalMode() {
return (float.IsNaN(Top) ? 0 : 1) + ((float.IsNaN(Vertical) && float.IsNaN(RelativeVertical)) ? 0 : 2) + (float.IsNaN(Bottom) ? 0 : 4);
}
public void Resize() {
if (AllowResize) {
// horizontal ::
// x and width
switch (horizontalMode()) {
case 0 :
Rect.x = Target.Left;
Rect.width = Target.Width;
break;
case 1 :
Rect.x = (int)Left;
Rect.width = (float.IsNaN(Width) ? Target.Width : (int)(Width < 0 ? -Parent.Width * Width : Width));
break;
case 2 :
Rect.width = (float.IsNaN(Width) ? Target.Width : (int)(Width < 0 ? - Parent.Width * Width : Width));
Rect.x = (int)((float.IsNaN(RelativeHorizontal) ? Parent.Width / 2 + Horizontal : Parent.Width * RelativeHorizontal) - Rect.width / 2);
break;
case 4 :
Rect.width = (float.IsNaN(Width) ? Target.Width : (int)(Width < 0 ? - Parent.Width * Width : Width));
Rect.x = (int)(Parent.Width - Right - Rect.width);
break;
case 3 :
Rect.x = (int)Left;
Rect.width = (int)( (float.IsNaN(RelativeHorizontal) ? Parent.Width / 2 + Horizontal : Parent.Width * RelativeHorizontal) - Left);
break;
case 5 :
Rect.x = (int)Left;
Rect.width = (int)(Parent.Width - Left - Right);
break;
case 6 :
Rect.x = (int)((float.IsNaN(RelativeHorizontal) ? Parent.Width / 2 + Horizontal : Parent.Width * RelativeHorizontal));
Rect.width = (int)(Parent.Width - Rect.x - Right );
break;
case 7 :
Rect.width = (float.IsNaN(Width) ? Target.Width : (int)(Width < 0 ? -Parent.Width * Width : Width));
float space = Parent.Width - Right - Left;
Rect.x = (int)((float.IsNaN(RelativeHorizontal) ? space/2 + RelativeHorizontal : space * RelativeHorizontal) + Left);
break;
}
// vertical ::
// y and height
switch (verticalMode()) {
case 0:
Rect.y = Target.Top;
Rect.height = Target.Height;
break;
case 1:
Rect.y = (int)Top;
Rect.height = (float.IsNaN(Height) ? Target.Height : (int)(Height < 0 ? Parent.Height * Height : Height));
break;
case 2:
Rect.height = (float.IsNaN(Height) ? Target.Height : (int)(Height < 0 ? Parent.Height * Height : Height));
Rect.y = (int)((float.IsNaN(RelativeVertical) ? Parent.Height / 2 + Vertical : Parent.Height * RelativeVertical) - Rect.height / 2);
break;
case 4:
Rect.height = (float.IsNaN(Height) ? Target.Height : (int)(Height < 0 ? Parent.Height * Height : Height));
Rect.y = (int)(Parent.Height - Bottom - Rect.height);
break;
case 3:
Rect.y = (int)Top;
Rect.height = (int)((float.IsNaN(RelativeVertical) ? Parent.Height / 2 + Vertical : Parent.Height * RelativeVertical) - Top);
break;
case 5:
Rect.y = (int)Top;
Rect.height = (int)(Parent.Height - Top - Bottom);
break;
case 6:
Rect.y = (int)((float.IsNaN(RelativeVertical) ? Parent.Height / 2 + Vertical : Parent.Height * RelativeVertical));
Rect.height = (int)(Parent.Height - Rect.y - Bottom);
break;
case 7:
Rect.height = (float.IsNaN(Height) ? Target.Height : (int)(Height < 0 ? Parent.Height * Height : Height));
float space = Parent.Height - Bottom - Top;
Rect.y = (int)((float.IsNaN(RelativeVertical) ? space / 2 + Vertical : space * RelativeVertical) + Top);
break;
}
Target.Left = Rect.x;
Target.Top = Rect.y;
Target.Width = Rect.width <= 0 ? Target.Width : Rect.width;
Target.Height = Rect.height <= 0 ? Target.Height : Rect.height;
if (Resized != null) {
Resized(this);
}
} else {
if (ResizeRequest != null) {
ResizeRequest(this);
}
}
}
public Rectangle GetPosition() {
return new Rectangle();
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------ UTIL
public override string ToString() {
return "[ Position :: target:"+ (Target == null ? "null" :Target.Name)+"]";
}
internal void internalRemove() {
Target = null;
Parent = null;
}
~Position() {
internalRemove();
}
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// <------------------------------
public struct Rectangle {
public int x;
public int y;
public int width;
public int height;
public override string ToString() {
return "[ :Rectangle: x:" + x +", y:"+y+", width:"+width + ", height:"+height+"]";
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.