// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-// Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
+// Copyright (c) 2005-2006 Novell, Inc. (http://www.novell.com)
//
// Authors:
// Peter Dennis Bartok (pbartok@novell.com)
[DefaultEvent("SplitterMoved")]
[Designer("System.Windows.Forms.Design.SplitterDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
[DefaultProperty("Dock")]
- public class Splitter : Control, IMessageFilter {
+ public class Splitter : Control
+#if !NET_2_0
+ , IMessageFilter
+#endif
+ {
#region Enums
private enum DrawType {
Initial,
#region Local Variables
static private Cursor splitter_ns;
static private Cursor splitter_we;
- private BorderStyle border_style;
+ // XXX this "new" shouldn't be here. Control shouldn't define border_style as internal.
+ new private BorderStyle border_style;
private int min_extra;
private int min_size;
private int split_position; // Current splitter position
private SplitterEventArgs sevent; // We cache the object, prevents fragmentation
private int limit_min; // The max we're allowed to move the splitter left/up
private int limit_max; // The max we're allowed to move the splitter right/down
+ private int split_requested; // If the user requests a position before we have ever laid out the doc
#endregion // Local Variables
#region Constructors
static Splitter() {
- try {
- splitter_ns = new Cursor(typeof(Splitter), "SpliterNS.cur");
- }
-
- catch (System.IO.FileNotFoundException) {
- splitter_ns = Cursors.SizeNS;
- }
-
- try {
- splitter_we = new Cursor(typeof(Splitter), "SplitterWE.cur");
- }
-
- catch (System.IO.FileNotFoundException) {
- splitter_we = Cursors.SizeWE;
- }
+ splitter_ns = Cursors.HSplit;
+ splitter_we = Cursors.VSplit;
}
public Splitter() {
min_extra = 25;
min_size = 25;
split_position = -1;
+ split_requested = -1;
splitter_size = 3;
horizontal = false;
sevent = new SplitterEventArgs(0, 0, 0, 0);
SetStyle(ControlStyles.Selectable, false);
Anchor = AnchorStyles.None;
+ Dock = DockStyle.Left;
- Paint += new PaintEventHandler(PaintSplitter);
Layout += new LayoutEventHandler(LayoutSplitter);
+ this.ParentChanged += new EventHandler(ReparentSplitter);
Cursor = splitter_we;
}
#endregion // Constructors
border_style = value;
switch(value) {
- case BorderStyle.FixedSingle: {
- splitter_size = 4; // We don't get motion events for 1px wide windows on X11. sigh.
- break;
- }
+ case BorderStyle.FixedSingle:
+ splitter_size = 4; // We don't get motion events for 1px wide windows on X11. sigh.
+ break;
- case BorderStyle.Fixed3D: {
- value = BorderStyle.None;
- splitter_size = 3;
- break;
- }
+ case BorderStyle.Fixed3D:
+ value = BorderStyle.None;
+ splitter_size = 3;
+ break;
- case BorderStyle.None: {
- splitter_size = 3;
- break;
- }
+ case BorderStyle.None:
+ splitter_size = 3;
+ break;
- default: {
- throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for BorderStyle", value));
- }
+ default:
+ throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for BorderStyle", value));
}
base.InternalBorderStyle = value;
[MWFCategory("Layout")]
public int SplitPosition {
get {
+ affected = AffectedControl;
if (affected == null) {
return -1;
}
}
set {
- if (Capture || (affected == null)) {
- return;
- }
+ affected = AffectedControl;
- if (horizontal) {
- affected.Height = value;
- } else {
- affected.Width = value;
+ if (affected == null) {
+ split_requested = value;
+ }
+ else {
+ if (horizontal) {
+ affected.Height = value;
+ } else {
+ affected.Width = value;
+ }
}
}
}
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public bool TabStop {
- get {
- return base.TabStop;
- }
-
- set {
- base.TabStop = value;
- }
+ public new bool TabStop {
+ get { return base.TabStop; }
+ set { base.TabStop = value; }
}
[Bindable(false)]
#endregion // Protected Instance Properties
#region Public Instance Methods
+#if !NET_2_0
public bool PreFilterMessage(ref Message m) {
return false;
}
+#endif
public override string ToString() {
return base.ToString () + String.Format(", MinExtra: {0}, MinSize: {1}", min_extra, min_size);
base.OnMouseDown (e);
// Only allow if we are set up properly
+ if ((affected == null) || (filler == null)) {
+ affected = AffectedControl;
+ filler = FillerControl;
+ }
+
if (affected == null || e.Button != MouseButtons.Left) {
return;
}
// Calculate limits
if (filler != null) {
if (horizontal) {
- if (dock_style == DockStyle.Top) {
+ if (Dock == DockStyle.Top) {
limit_min = affected.Bounds.Top + min_size;
limit_max = filler.Bounds.Bottom - min_extra + this.bounds.Top - filler.Bounds.Top;
} else {
limit_max = affected.Bounds.Bottom - min_size - this.Height;
}
} else {
- if (dock_style == DockStyle.Left) {
+ if (Dock == DockStyle.Left) {
limit_min = affected.Bounds.Left + min_size;
limit_max = filler.Bounds.Right - min_extra + this.bounds.Left - filler.Bounds.Left;
} else {
Console.WriteLine("Sizing limits: Min:{0}, Max:{1}", limit_min, limit_max);
#endif
- pt = PointToScreen(parent.PointToClient(new Point(e.X, e.Y)));
+ pt = PointToScreen(Parent.PointToClient(new Point(e.X, e.Y)));
if (horizontal) {
split_position = pt.Y;
- if (dock_style == DockStyle.Top) {
+ if (Dock == DockStyle.Top) {
click_offset = e.Y;
} else {
click_offset = -e.Y;
}
} else {
split_position = pt.X;
- if (dock_style == DockStyle.Left) {
+ if (Dock == DockStyle.Left) {
click_offset = e.X;
} else {
click_offset = -e.X;
base.OnMouseMove (e);
- if (!Capture || e.Button != MouseButtons.Left) {
+ if (!Capture || e.Button != MouseButtons.Left || affected == null) {
return;
}
// We need our mouse coordinates relative to our parent
- pt = PointToScreen(parent.PointToClient(new Point(e.X, e.Y)));
+ pt = PointToScreen(Parent.PointToClient(new Point(e.X, e.Y)));
// Grab our new coordinates
prev_split_position = split_position;
- if (horizontal) {
- split_position = pt.Y;
- } else {
- split_position = pt.X;
- }
+
+ int candidate = horizontal ? pt.Y : pt.X;
+
+ // Enforce limit on what we send to the event
+ if (candidate < limit_min)
+ candidate = limit_min;
+ else if (candidate > limit_max)
+ candidate = limit_max;
+
+ sevent.x = pt.X;
+ sevent.y = pt.Y;
+ sevent.split_x = horizontal ? 0 : candidate;
+ sevent.split_y = horizontal ? candidate : 0;
+
+ // Fire the event
+ OnSplitterMoving(sevent);
+
+ split_position = horizontal ? sevent.split_y : sevent.split_x;
+
// Enforce limits
if (split_position < limit_min) {
#if Debug
split_position = limit_max;
}
- // Don't waste cycles
- if (prev_split_position != split_position) {
- // Update our handle location
- DrawDragHandle(DrawType.Redraw);
- }
-
- // Prepare the event
- if (horizontal) {
- sevent.split_x = 0;
- sevent.split_y = split_position;
- } else {
- sevent.split_x = split_position;
- sevent.split_y = 0;
- }
-
- sevent.x = pt.X;
- sevent.y = pt.Y;
-
- // Fire the event
- OnSplitterMoving(sevent);
+ // Update our handle location
+ DrawDragHandle(DrawType.Redraw);
}
protected override void OnMouseUp(MouseEventArgs e) {
- if (!Capture || e.Button != MouseButtons.Left) {
+ if (!Capture || e.Button != MouseButtons.Left || affected == null) {
base.OnMouseUp (e);
return;
}
}
protected virtual void OnSplitterMoved(SplitterEventArgs sevent) {
- if (SplitterMoved != null) {
- SplitterMoved(this, sevent);
- }
+ SplitterEventHandler eh = (SplitterEventHandler)(Events [SplitterMovedEvent]);
+ if (eh != null)
+ eh (this, sevent);
}
protected virtual void OnSplitterMoving(SplitterEventArgs sevent) {
- if (SplitterMoving != null) {
- SplitterMoving(this, sevent);
- }
+ SplitterEventHandler eh = (SplitterEventHandler)(Events [SplitterMovingEvent]);
+ if (eh != null)
+ eh (this, sevent);
}
protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
// enforce our width / height
if (horizontal) {
+ splitter_size = height;
+ if (splitter_size < 1) {
+ splitter_size = 3;
+ }
base.SetBoundsCore (x, y, width, splitter_size, specified);
} else {
+ splitter_size = width;
+ if (splitter_size < 1) {
+ splitter_size = 3;
+ }
base.SetBoundsCore (x, y, splitter_size, height, specified);
}
}
#region Private Properties and Methods
private Control AffectedControl {
get {
- if (parent == null) {
+ if (Parent == null)
return null;
- }
// Doc says the first control preceeding us in the zorder
- for (int i = parent.Controls.GetChildIndex(this) + 1; i < parent.Controls.Count; i++) {
- switch(this.Dock) {
- case DockStyle.Top: {
- if (Top == parent.Controls[i].Bottom) {
- return parent.Controls[i];
- }
- break;
- }
-
- case DockStyle.Bottom: {
- if (Bottom == parent.Controls[i].Top) {
- return parent.Controls[i];
- }
- break;
- }
-
- case DockStyle.Left: {
- if (Left == parent.Controls[i].Right) {
- return parent.Controls[i];
- }
- break;
- }
-
- case DockStyle.Right: {
- if (Right == parent.Controls[i].Left) {
- return parent.Controls[i];
- }
- break;
- }
+ for (int i = Parent.Controls.GetChildIndex(this) + 1; i < Parent.Controls.Count; i++) {
+ switch (Dock) {
+ case DockStyle.Top:
+ if (Top == Parent.Controls[i].Bottom)
+ return Parent.Controls[i];
+ break;
+ case DockStyle.Bottom:
+ if (Bottom == Parent.Controls[i].Top)
+ return Parent.Controls[i];
+ break;
+ case DockStyle.Left:
+ if (Left == Parent.Controls[i].Right)
+ return Parent.Controls[i];
+ break;
+ case DockStyle.Right:
+ if (Right == Parent.Controls[i].Left)
+ return Parent.Controls[i];
+ break;
}
}
return null;
private Control FillerControl {
get {
- if (parent == null) {
+ if (Parent == null)
return null;
- }
// Doc says the first control preceeding us in the zorder
- for (int i = parent.Controls.GetChildIndex(this) - 1; i >= 0; i--) {
- if (parent.Controls[i].Dock == DockStyle.Fill) {
- return parent.Controls[i];
+ for (int i = Parent.Controls.GetChildIndex(this) - 1; i >= 0; i--) {
+ if (Parent.Controls[i].Dock == DockStyle.Fill) {
+ return Parent.Controls[i];
}
}
return null;
private int CalculateSplitPosition() {
if (horizontal) {
- if (dock_style == DockStyle.Top) {
- return split_position;
- } else {
+ if (Dock == DockStyle.Top)
+ return split_position - affected.Top;
+ else
return affected.Bottom - split_position - splitter_size;
- }
} else {
- if (dock_style == DockStyle.Left) {
- return split_position;
- } else {
+ if (Dock == DockStyle.Left)
+ return split_position - affected.Left;
+ else
return affected.Right - split_position - splitter_size;
- }
}
}
- private void PaintSplitter(object sender, PaintEventArgs e) {
+ internal override void OnPaintInternal (PaintEventArgs e) {
e.Graphics.FillRectangle(ThemeEngine.Current.ResPool.GetSolidBrush(this.BackColor), e.ClipRectangle);
}
private void LayoutSplitter(object sender, LayoutEventArgs e) {
affected = AffectedControl;
filler = FillerControl;
+ if (split_requested != -1) {
+ SplitPosition = split_requested;
+ split_requested = -1;
+ }
+ }
+
+ private void ReparentSplitter(object sender, EventArgs e) {
+ affected = null;
+ filler = null;
}
private void DrawDragHandle(DrawType type) {
Rectangle current;
if (horizontal) {
- prev = new Rectangle(0, prev_split_position - click_offset + 1, Width, 0);
- current = new Rectangle(0, split_position - click_offset + 1, Width, 0);
+ prev = new Rectangle(Location.X, prev_split_position - click_offset + 1, Width, 0);
+ current = new Rectangle(Location.X, split_position - click_offset + 1, Width, 0);
} else {
- prev = new Rectangle(prev_split_position - click_offset + 1, 0, 0, Height);
- current = new Rectangle(split_position - click_offset + 1, 0, 0, Height);
+ prev = new Rectangle(prev_split_position - click_offset + 1, Location.Y, 0, Height);
+ current = new Rectangle(split_position - click_offset + 1, Location.Y, 0, Height);
}
switch(type) {
- case DrawType.Initial: {
- XplatUI.DrawReversibleRectangle(Parent.window.Handle, current, 3);
- return;
- }
-
- case DrawType.Redraw: {
- if (prev.X == current.X && prev.Y == current.Y) {
- return;
- }
+ case DrawType.Initial:
+ XplatUI.DrawReversibleRectangle(Parent.window.Handle, current, 3);
+ return;
- XplatUI.DrawReversibleRectangle(Parent.window.Handle, prev, 3);
- XplatUI.DrawReversibleRectangle(Parent.window.Handle, current, 3);
+ case DrawType.Redraw:
+ if (prev.X == current.X && prev.Y == current.Y)
return;
- }
- case DrawType.Finish: {
- XplatUI.DrawReversibleRectangle(Parent.window.Handle, prev, 3);
- return;
- }
+ XplatUI.DrawReversibleRectangle(Parent.window.Handle, prev, 3);
+ XplatUI.DrawReversibleRectangle(Parent.window.Handle, current, 3);
+ return;
+
+ case DrawType.Finish:
+ XplatUI.DrawReversibleRectangle(Parent.window.Handle, current, 3);
+ return;
}
}
#endregion // Private Properties and Methods
#region Events
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler BackgroundImageChanged;
+ public new event EventHandler BackgroundImageChanged {
+ add { base.BackgroundImageChanged += value; }
+ remove { base.BackgroundImageChanged -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler Enter;
+ public new event EventHandler Enter {
+ add { base.Enter += value; }
+ remove { base.Enter -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler FontChanged;
+ public new event EventHandler FontChanged {
+ add { base.FontChanged += value; }
+ remove { base.FontChanged -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler ForeColorChanged;
+ public new event EventHandler ForeColorChanged {
+ add { base.ForeColorChanged += value; }
+ remove { base.ForeColorChanged -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler ImeModeChanged;
+ public new event EventHandler ImeModeChanged {
+ add { base.ImeModeChanged += value; }
+ remove { base.ImeModeChanged -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event KeyEventHandler KeyDown;
+ public new event KeyEventHandler KeyDown {
+ add { base.KeyDown += value; }
+ remove { base.KeyDown -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event KeyPressEventHandler KeyPress;
+ public new event KeyPressEventHandler KeyPress {
+ add { base.KeyPress += value; }
+ remove { base.KeyPress -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event KeyEventHandler KeyUp;
+ public new event KeyEventHandler KeyUp {
+ add { base.KeyUp += value; }
+ remove { base.KeyUp -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler Leave;
+ public new event EventHandler Leave {
+ add { base.Leave += value; }
+ remove { base.Leave -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler TabStopChanged;
+ public new event EventHandler TabStopChanged {
+ add { base.TabStopChanged += value; }
+ remove { base.TabStopChanged -= value; }
+ }
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
- public new event EventHandler TextChanged;
+ public new event EventHandler TextChanged {
+ add { base.TextChanged += value; }
+ remove { base.TextChanged -= value; }
+ }
+
+ static object SplitterMovedEvent = new object ();
+ static object SplitterMovingEvent = new object ();
- public event SplitterEventHandler SplitterMoved;
- public event SplitterEventHandler SplitterMoving;
+ public event SplitterEventHandler SplitterMoved {
+ add { Events.AddHandler (SplitterMovedEvent, value); }
+ remove { Events.RemoveHandler (SplitterMovedEvent, value); }
+ }
+
+ public event SplitterEventHandler SplitterMoving {
+ add { Events.AddHandler (SplitterMovingEvent, value); }
+ remove { Events.RemoveHandler (SplitterMovingEvent, value); }
+ }
#endregion // Events
}
}