diff options
| author | Michael VanOverbeek <[email protected]> | 2016-07-25 12:57:52 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2016-07-25 12:57:52 -0400 |
| commit | 46c1c31302f111a1f3ec23a70e6f3986a9aa2a27 (patch) | |
| tree | f00af7ea3f6ad2641fb26fa1d310fd8b7179b39c /source/ShiftUI/Design | |
| parent | af48e774189596b8d7a058c564a7d6d75205ca03 (diff) | |
| parent | 6fa16209519896de09949a27425dff00ebf2970a (diff) | |
| download | shiftos-c--46c1c31302f111a1f3ec23a70e6f3986a9aa2a27.tar.gz shiftos-c--46c1c31302f111a1f3ec23a70e6f3986a9aa2a27.tar.bz2 shiftos-c--46c1c31302f111a1f3ec23a70e6f3986a9aa2a27.zip | |
Merge pull request #17 from MichaelTheShifter/shiftui_integration
Shiftui integration
Diffstat (limited to 'source/ShiftUI/Design')
42 files changed, 7134 insertions, 0 deletions
diff --git a/source/ShiftUI/Design/Behavior/Adorner.cs b/source/ShiftUI/Design/Behavior/Adorner.cs new file mode 100644 index 0000000..f67c6af --- /dev/null +++ b/source/ShiftUI/Design/Behavior/Adorner.cs @@ -0,0 +1,81 @@ +// +// ShiftUI.Design.Behavior.Adorner +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Drawing; +using System.Drawing.Design; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Design.Behavior +{ + public sealed class Adorner + { + public Adorner () + { + } + + [MonoTODO] + public void Invalidate () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void Invalidate (Rectangle rectangle) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void Invalidate (Region region) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public BehaviorService BehaviorService { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + + [MonoTODO] + public bool Enabled { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } + + [MonoTODO] + public GlyphCollection Glyphs { + get { throw new NotImplementedException (); } + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/Behavior.cs b/source/ShiftUI/Design/Behavior/Behavior.cs new file mode 100644 index 0000000..df6185a --- /dev/null +++ b/source/ShiftUI/Design/Behavior/Behavior.cs @@ -0,0 +1,155 @@ +// +// ShiftUI.Design.Behavior.Behavior +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.ComponentModel.Design; +using System.Drawing; +using System.Drawing.Design; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Design.Behavior +{ + public abstract class Behavior + { + [MonoTODO] + protected Behavior () + { + throw new NotImplementedException (); + } + + [MonoTODO] + protected Behavior (bool callParentBehavior, BehaviorService behaviorService) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual Cursor Cursor { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public virtual bool DisableAllCommands { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public virtual MenuCommand FindCommand (CommandID commandId) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnDragDrop (Glyph g, DragEventArgs e) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnDragEnter (Glyph g, DragEventArgs e) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnDragLeave (Glyph g, EventArgs e) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnDragOver (Glyph g, DragEventArgs e) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnGiveFeedback (Glyph g, GiveFeedbackEventArgs e) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnLoseCapture (Glyph g, EventArgs e) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseDoubleClick (Glyph g, MouseButtons button, Point mouseLoc) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseDown (Glyph g, MouseButtons button, Point mouseLoc) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseEnter (Glyph g) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseHover (Glyph g, Point mouseLoc) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseLeave (Glyph g) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseMove (Glyph g, MouseButtons button, Point mouseLoc) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual bool OnMouseUp (Glyph g, MouseButtons button) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual void OnQueryContinueDrag (Glyph g, QueryContinueDragEventArgs e) + { + throw new NotImplementedException (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/BehaviorDragDropEventArgs.cs b/source/ShiftUI/Design/Behavior/BehaviorDragDropEventArgs.cs new file mode 100644 index 0000000..9a22361 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/BehaviorDragDropEventArgs.cs @@ -0,0 +1,50 @@ +// +// ShiftUI.Design.Behavior.BehaviorDragDropEventArgs +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; + +namespace ShiftUI.Design.Behavior +{ + public class BehaviorDragDropEventArgs : EventArgs + { + ICollection components; + + public BehaviorDragDropEventArgs (ICollection dragComponents) + { + this.components = dragComponents; + } + + public ICollection DragComponents { + get { return components; } + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/BehaviorDragDropEventHandler.cs b/source/ShiftUI/Design/Behavior/BehaviorDragDropEventHandler.cs new file mode 100644 index 0000000..83c1ef3 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/BehaviorDragDropEventHandler.cs @@ -0,0 +1,36 @@ +// +// ShiftUI.Design.Behavior.BehaviorDragDropEventHandler +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +namespace ShiftUI.Design.Behavior +{ + public delegate void BehaviorDragDropEventHandler (object sender, BehaviorDragDropEventArgs e); +} + diff --git a/source/ShiftUI/Design/Behavior/BehaviorService.cs b/source/ShiftUI/Design/Behavior/BehaviorService.cs new file mode 100644 index 0000000..cc741b1 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/BehaviorService.cs @@ -0,0 +1,154 @@ +// +// ShiftUI.Design.Behavior.BehaviorService +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Design.Behavior +{ + public sealed class BehaviorService : IDisposable + { + internal BehaviorService () + { + } + + public event BehaviorDragDropEventHandler BeginDrag; + public event BehaviorDragDropEventHandler EndDrag; + public event EventHandler Synchronize; + + [MonoTODO] + public BehaviorServiceAdornerCollection Adorners { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public Graphics AdornerWindowGraphics { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public Behavior CurrentBehavior { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public Point AdornerWindowPointToScreen (Point p) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Point AdornerWindowToScreen () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Rectangle WidgetRectInAdornerWindow (Widget c) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Point WidgetToAdornerWindow (Widget c) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void Dispose () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Behavior GetNextBehavior (Behavior behavior) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void Invalidate () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void Invalidate (Rectangle rect) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void Invalidate (Region r) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Point MapAdornerWindowPoint (IntPtr handle, Point pt) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Behavior PopBehavior (Behavior behavior) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void PushBehavior (Behavior behavior) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void PushCaptureBehavior (Behavior behavior) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public Point ScreenToAdornerWindow (Point p) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void SyncSelection () + { + throw new NotImplementedException (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/BehaviorServiceAdornerCollection.cs b/source/ShiftUI/Design/Behavior/BehaviorServiceAdornerCollection.cs new file mode 100644 index 0000000..2850cd4 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/BehaviorServiceAdornerCollection.cs @@ -0,0 +1,128 @@ +// +// ShiftUI.Design.Behavior.BehaviorServiceAdornerCollection +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Collections; + +namespace ShiftUI.Design.Behavior +{ + public sealed class BehaviorServiceAdornerCollection : CollectionBase + { + int state; + + public BehaviorServiceAdornerCollection (BehaviorService behaviorService) + : this (behaviorService.Adorners) + { + } + + public BehaviorServiceAdornerCollection (Adorner [] value) + { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public BehaviorServiceAdornerCollection (BehaviorServiceAdornerCollection value) + { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + internal int State { + get { return state; } + } + + public Adorner this [int index] { + get { return (Adorner) InnerList [index]; } + set { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList [index] = value; + } + } + + public int Add (Adorner value) + { + state++; + return InnerList.Add (value); + } + + public void AddRange (Adorner [] value) + { + state++; + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public void AddRange (BehaviorServiceAdornerCollection value) + { + state++; + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public bool Contains (Adorner value) + { + return InnerList.Contains (value); + } + + public void CopyTo (Adorner [] array, int index) + { + InnerList.CopyTo (array, index); + } + + public int IndexOf (Adorner value) + { + return InnerList.IndexOf (value); + } + + public BehaviorServiceAdornerCollectionEnumerator GetEnumerator () + { + return new BehaviorServiceAdornerCollectionEnumerator (this); + } + + public void Insert (int index, Adorner value) + { + state++; + InnerList.Insert (index, value); + } + + public void Remove (Adorner value) + { + state++; + InnerList.Remove (value); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/BehaviorServiceAdornerCollectionEnumerator.cs b/source/ShiftUI/Design/Behavior/BehaviorServiceAdornerCollectionEnumerator.cs new file mode 100644 index 0000000..a4e9138 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/BehaviorServiceAdornerCollectionEnumerator.cs @@ -0,0 +1,90 @@ +// +// ShiftUI.Design.Behavior.BehaviorServiceAdornerCollectionEnumerator +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Collections; + +namespace ShiftUI.Design.Behavior +{ + public class BehaviorServiceAdornerCollectionEnumerator : IEnumerator + { + BehaviorServiceAdornerCollection mappings; + int index, state; + + public BehaviorServiceAdornerCollectionEnumerator (BehaviorServiceAdornerCollection mappings) + { + if (mappings == null) + throw new ArgumentNullException ("mappings"); + this.mappings = mappings; + + Reset (); + } + + public Adorner Current { + get { return index < 0 ? null : mappings [index]; } + } + + void CheckState () + { + if (mappings.State != state) + throw new InvalidOperationException ("Collection has changed"); + } + + public bool MoveNext () + { + CheckState (); + if (index++ < mappings.Count) + return true; + index--; + return false; + } + + public void Reset () + { + index = -1; + } + + object IEnumerator.Current { + get { return Current; } + } + + bool IEnumerator.MoveNext () + { + return MoveNext (); + } + + void IEnumerator.Reset () + { + Reset (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/ComponentGlyph.cs b/source/ShiftUI/Design/Behavior/ComponentGlyph.cs new file mode 100644 index 0000000..0f8c53b --- /dev/null +++ b/source/ShiftUI/Design/Behavior/ComponentGlyph.cs @@ -0,0 +1,73 @@ +// +// ShiftUI.Design.Behavior.ComponentGlyph +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Design; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Design.Behavior +{ + public class ComponentGlyph : Glyph + { + IComponent component; + + public ComponentGlyph (IComponent relatedComponent) + : this (relatedComponent, null) + { + } + + public ComponentGlyph (IComponent relatedComponent, Behavior behavior) + : base (behavior) + { + this.component = relatedComponent; + } + + [MonoTODO] + public IComponent RelatedComponent { + get { return component; } + } + + [MonoTODO] + public override Cursor GetHitTest (Point p) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override void Paint (PaintEventArgs pe) + { + throw new NotImplementedException (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/ControlBodyGlyph.cs b/source/ShiftUI/Design/Behavior/ControlBodyGlyph.cs new file mode 100644 index 0000000..547eea1 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/ControlBodyGlyph.cs @@ -0,0 +1,70 @@ +// +// ShiftUI.Design.Behavior.WidgetBodyGlyph +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Design; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Design.Behavior +{ + public class WidgetBodyGlyph : ComponentGlyph + { + Rectangle bounds; + + [MonoTODO] + public WidgetBodyGlyph (Rectangle bounds, Cursor cursor, IComponent relatedComponent, Behavior behavior) + : base (relatedComponent, behavior) + { + this.bounds = bounds; + throw new NotImplementedException (); + } + + [MonoTODO] + public WidgetBodyGlyph (Rectangle bounds, Cursor cursor, IComponent relatedComponent, WidgetDesigner designer) + : this (bounds, cursor, relatedComponent, designer.BehaviorService.CurrentBehavior) + { + } + + [MonoTODO] + public override Rectangle Bounds { + get { return bounds; } + } + + [MonoTODO] + public override Cursor GetHitTest (Point p) + { + throw new NotImplementedException (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/Glyph.cs b/source/ShiftUI/Design/Behavior/Glyph.cs new file mode 100644 index 0000000..3452627 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/Glyph.cs @@ -0,0 +1,70 @@ +// +// ShiftUI.Design.Behavior.Glyph +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Drawing; +using System.Drawing.Design; +using System.Drawing.Drawing2D; + +namespace ShiftUI.Design.Behavior +{ + public abstract class Glyph + { + Behavior behavior; + + [MonoTODO] + protected Glyph (Behavior behavior) + { + SetBehavior (behavior); + } + + [MonoTODO] + public virtual Behavior Behavior { + get { return behavior; } + } + + [MonoTODO] + public virtual Rectangle Bounds { + get { throw new NotImplementedException (); } + } + + public abstract Cursor GetHitTest (Point p); + + public abstract void Paint (PaintEventArgs pe); + + [MonoTODO] + protected void SetBehavior (Behavior behavior) + { + throw new NotImplementedException (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/GlyphCollection.cs b/source/ShiftUI/Design/Behavior/GlyphCollection.cs new file mode 100644 index 0000000..d19e689 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/GlyphCollection.cs @@ -0,0 +1,111 @@ +// +// ShiftUI.Design.Behavior.GlyphCollection +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Collections; + +namespace ShiftUI.Design.Behavior +{ + public class GlyphCollection : CollectionBase + { + public GlyphCollection () + { + } + + public GlyphCollection (Glyph [] value) + { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public GlyphCollection (GlyphCollection value) + { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public Glyph this [int index] { + get { return (Glyph) InnerList [index]; } + set { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList [index] = value; + } + } + + public int Add (Glyph value) + { + return InnerList.Add (value); + } + + public void AddRange (Glyph [] value) + { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public void AddRange (GlyphCollection value) + { + if (value == null) + throw new ArgumentNullException ("value"); + InnerList.AddRange (value); + } + + public bool Contains (Glyph value) + { + return InnerList.Contains (value); + } + + public void CopyTo (Glyph [] array, int index) + { + InnerList.CopyTo (array, index); + } + + public int IndexOf (Glyph value) + { + return InnerList.IndexOf (value); + } + + public void Insert (int index, Glyph value) + { + InnerList.Insert (index, value); + } + + public void Remove (Glyph value) + { + InnerList.Remove (value); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/GlyphSelectionType.cs b/source/ShiftUI/Design/Behavior/GlyphSelectionType.cs new file mode 100644 index 0000000..6220c03 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/GlyphSelectionType.cs @@ -0,0 +1,41 @@ +// +// ShiftUI.Design.Behavior.GlyphSelectionType +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +namespace ShiftUI.Design.Behavior +{ + public enum GlyphSelectionType + { + NotSelected, + Selected, + SelectedPrimary + } +} + diff --git a/source/ShiftUI/Design/Behavior/SnapLine.cs b/source/ShiftUI/Design/Behavior/SnapLine.cs new file mode 100644 index 0000000..3b7da92 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/SnapLine.cs @@ -0,0 +1,133 @@ +// +// ShiftUI.Design.Behavior.SnapLine +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + + +using System; + +namespace ShiftUI.Design.Behavior +{ + public sealed class SnapLine + { + [MonoTODO] + public static bool ShouldSnap (SnapLine line1, SnapLine line2) + { + throw new NotImplementedException (); + } + + SnapLineType type; + int offset; + string filter; + SnapLinePriority priority; + + [MonoTODO] + public SnapLine (SnapLineType type, int offset) + : this (type, offset, null) + { + } + + [MonoTODO] + public SnapLine (SnapLineType type, int offset, string filter) + : this (type, offset, filter, default (SnapLinePriority)) + { + } + + [MonoTODO] + public SnapLine (SnapLineType type, int offset, SnapLinePriority priority) + : this (type, offset, null, priority) + { + } + + [MonoTODO] + public SnapLine (SnapLineType type, int offset, string filter, SnapLinePriority priority) + { + this.type =type; + this.offset = offset; + this.filter = filter; + this.priority = priority; + } + + public string Filter { + get { return filter; } + } + + public bool IsHorizontal { + get { + switch (SnapLineType) { + case SnapLineType.Top: + case SnapLineType.Bottom: + case SnapLineType.Horizontal: + case SnapLineType.Baseline: + return true; + default: + return false; + } + } + } + + public bool IsVertical { + get { + switch (SnapLineType) { + case SnapLineType.Left: + case SnapLineType.Right: + case SnapLineType.Vertical: + return true; + default: + return false; + } + } + } + + public int Offset { + get { return offset; } + } + + public SnapLinePriority Priority { + get { return priority; } + } + + public SnapLineType SnapLineType { + get { return type; } + } + + [MonoTODO] + public void AdjustOffset (int adjustment) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override string ToString () + { + return base.ToString (); + } + } +} + diff --git a/source/ShiftUI/Design/Behavior/SnapLinePriority.cs b/source/ShiftUI/Design/Behavior/SnapLinePriority.cs new file mode 100644 index 0000000..b0dff04 --- /dev/null +++ b/source/ShiftUI/Design/Behavior/SnapLinePriority.cs @@ -0,0 +1,42 @@ +// +// ShiftUI.Design.Behavior.SnapLinePriority +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +namespace ShiftUI.Design.Behavior +{ + public enum SnapLinePriority + { + Low = 1, + Medium, + High, + Always + } +} + diff --git a/source/ShiftUI/Design/Behavior/SnapLineType.cs b/source/ShiftUI/Design/Behavior/SnapLineType.cs new file mode 100644 index 0000000..a0b294b --- /dev/null +++ b/source/ShiftUI/Design/Behavior/SnapLineType.cs @@ -0,0 +1,45 @@ +// +// ShiftUI.Design.Behavior.SnapLineType +// +// Author: +// Atsushi Enomoto ([email protected]) +// +// Copyright (C) 2007 Novell, Inc. +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +namespace ShiftUI.Design.Behavior +{ + public enum SnapLineType + { + Top, + Bottom, + Left, + Right, + Horizontal, + Vertical, + Baseline + } +} + diff --git a/source/ShiftUI/Design/ComponentDesigner.cs b/source/ShiftUI/Design/ComponentDesigner.cs new file mode 100644 index 0000000..f0034b6 --- /dev/null +++ b/source/ShiftUI/Design/ComponentDesigner.cs @@ -0,0 +1,438 @@ +// +// System.ComponentModel.Design.ComponentDesigner +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; + +namespace ShiftUI.Design +{ + + public class ComponentDesigner : ITreeDesigner, IDesigner, IDisposable, IDesignerFilter, IComponentInitializer + { + +#region ShadowPropertyCollection + + protected sealed class ShadowPropertyCollection + { + + private Hashtable _properties = null; + private IComponent _component; + + internal ShadowPropertyCollection (IComponent component) + { + _component = component; + } + + // Returns Widget's property value (if available) if there is no shadowed one. + // + public object this[string propertyName] + { + get { + if (propertyName == null) + throw new System.ArgumentNullException("propertyName"); + + if (_properties != null && _properties.ContainsKey (propertyName)) + return _properties[propertyName]; + + PropertyDescriptor property = TypeDescriptor.GetProperties (_component.GetType ())[propertyName]; + if (property != null) + return property.GetValue (_component); + else + throw new System.Exception ("Propery not found!"); + } + set { + if (_properties == null) + _properties = new Hashtable (); + _properties[propertyName] = value; + } + } + + public bool Contains (string propertyName) + { + if (_properties != null) + return _properties.ContainsKey (propertyName); + else + return false; + } + + } // ShadowPropertyCollection +#endregion + + public ComponentDesigner () + { + } + + + private IComponent _component; + private DesignerVerbCollection _verbs; + private ShadowPropertyCollection _shadowPropertyCollection; + private DesignerActionListCollection _designerActionList; + + // This property indicates any components to copy or move along with the component managed + // by the designer during a copy, drag, or move operation. + // If this collection contains references to other components in the current design mode document, + // those components will be copied along with the component managed by the designer during a copy operation. + // When the component managed by the designer is selected, this collection is filled with any nested controls. + // This collection can also include other components, such as the buttons of a toolbar. + // + // supposedly contains all the children of the component, thus used for ITreeDesigner.Children + // + public virtual ICollection AssociatedComponents { + get { return new IComponent[0]; } + } + + public IComponent Component { + get { return _component; } + } + + public virtual DesignerVerbCollection Verbs { + get { + if (_verbs == null) + _verbs = new DesignerVerbCollection (); + + return _verbs; + } + } + + protected virtual InheritanceAttribute InheritanceAttribute { + get { + IInheritanceService service = (IInheritanceService) this.GetService (typeof (IInheritanceService)); + if (service != null) + return service.GetInheritanceAttribute (_component); + else + return InheritanceAttribute.Default; + } + } + + protected bool Inherited { + get { return !this.InheritanceAttribute.Equals (InheritanceAttribute.NotInherited); } + } + + //Gets a collection of property values that override user settings. + // + protected ShadowPropertyCollection ShadowProperties { + get { + if (_shadowPropertyCollection == null) { + _shadowPropertyCollection = new ShadowPropertyCollection(_component); + } + return _shadowPropertyCollection; + } + } + + public virtual DesignerActionListCollection ActionLists { + get { + if (_designerActionList == null) + _designerActionList = new DesignerActionListCollection (); + + return _designerActionList; + } + } + + protected virtual IComponent ParentComponent { + get { + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host != null) { + IComponent rootComponent = host.RootComponent; + if (rootComponent != _component) + return rootComponent; + } + return null; + } + } + + public virtual void InitializeNewComponent (IDictionary defaultValues) + { + // Reset + // + OnSetComponentDefaults (); + } + + // MSDN: The default implementation of this method does nothing. + // + public virtual void InitializeExistingComponent (IDictionary defaultValues) + { + InitializeNonDefault (); + } + + + public virtual void Initialize (IComponent component) + { + if (component == null) + throw new ArgumentNullException ("component"); + + _component = component; + } + + [Obsolete ("This method has been deprecated. Use InitializeExistingComponent instead.")] + public virtual void InitializeNonDefault () + { + } + + + // This method is called when a user double-clicks (the representation of) a component. + // Tries to bind the default event to a method or creates a new one. + // + public virtual void DoDefaultAction() + { + IDesignerHost host = (IDesignerHost) this.GetService(typeof(IDesignerHost)); + DesignerTransaction transaction = null; + if (host != null) + transaction = host.CreateTransaction ("ComponentDesigner_AddEvent"); + + IEventBindingService eventBindingService = GetService (typeof(IEventBindingService)) as IEventBindingService; + EventDescriptor defaultEventDescriptor = null; + + if (eventBindingService != null) { + ISelectionService selectionService = this.GetService (typeof (ISelectionService)) as ISelectionService; + try { + if (selectionService != null) { + ICollection selectedComponents = selectionService.GetSelectedComponents (); + + foreach (IComponent component in selectedComponents) { + EventDescriptor eventDescriptor = TypeDescriptor.GetDefaultEvent (component); + if (eventDescriptor != null) { + PropertyDescriptor eventProperty = eventBindingService.GetEventProperty (eventDescriptor); + if (eventProperty != null && !eventProperty.IsReadOnly) { + string methodName = eventProperty.GetValue (component) as string; + bool newMethod = true; + + if (methodName != null || methodName != String.Empty) { + ICollection compatibleMethods = eventBindingService.GetCompatibleMethods (eventDescriptor); + foreach (string signature in compatibleMethods) { + if (signature == methodName) { + newMethod = false; + break; + } + } + } + if (newMethod) { + if (methodName == null) + methodName = eventBindingService.CreateUniqueMethodName (component, eventDescriptor); + + eventProperty.SetValue (component, methodName); + } + + if (component == _component) + defaultEventDescriptor = eventDescriptor; + } + } + } + + } + } + catch { + if (transaction != null) { + transaction.Cancel (); + transaction = null; + } + } + finally { + if (transaction != null) + transaction.Commit (); + } + + if (defaultEventDescriptor != null) + eventBindingService.ShowCode (_component, defaultEventDescriptor); + } + } + + + + [Obsolete ("This method has been deprecated. Use InitializeNewComponent instead.")] + // The default implementation of this method sets the default property of the component to + // the name of the component if the default property is a string and the property is not already set. + // This method can be implemented in a derived class to customize the initialization of the component + // that this designer is designing. + // + public virtual void OnSetComponentDefaults () + { + if (_component != null && _component.Site != null) { + PropertyDescriptor property = TypeDescriptor.GetDefaultProperty (_component); + if (property != null && property.PropertyType.Equals (typeof (string))) { + string propertyValue = (string)property.GetValue (_component); + if (propertyValue != null && propertyValue.Length != 0) + property.SetValue (_component, _component.Site.Name); + } + } + } + + + + + protected InheritanceAttribute InvokeGetInheritanceAttribute (ComponentDesigner toInvoke) + { + return toInvoke.InheritanceAttribute; + } + +#region IDesignerFilter + + // TypeDescriptor queries the component's site for ITypeDescriptorFilterService + // then invokes ITypeDescriptorFilterService.XXXX before retrieveing props/event/attributes, + // which then invokes the IDesignerFilter implementation of the component + // + protected virtual void PostFilterAttributes (IDictionary attributes) + { + } + + protected virtual void PostFilterEvents (IDictionary events) + { + } + + protected virtual void PostFilterProperties (IDictionary properties) + { + } + + protected virtual void PreFilterAttributes (IDictionary attributes) + { + } + + protected virtual void PreFilterEvents (IDictionary events) + { + } + + protected virtual void PreFilterProperties (IDictionary properties) + { + } +#endregion + + protected void RaiseComponentChanged (MemberDescriptor member, object oldValue, object newValue) + { + IComponentChangeService service = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + if (service != null) + service.OnComponentChanged (_component, member, oldValue, newValue); + } + + protected void RaiseComponentChanging (MemberDescriptor member) + { + IComponentChangeService service = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + if (service != null) + service.OnComponentChanging (_component, member); + } + +#region Implementation of IDesignerFilter + + void IDesignerFilter.PostFilterAttributes (IDictionary attributes) + { + PostFilterAttributes (attributes); + } + + void IDesignerFilter.PostFilterEvents (IDictionary events) + { + PostFilterEvents (events); + } + + void IDesignerFilter.PostFilterProperties (IDictionary properties) + { + PostFilterProperties (properties); + } + + void IDesignerFilter.PreFilterAttributes (IDictionary attributes) + { + PreFilterAttributes (attributes); + } + + void IDesignerFilter.PreFilterEvents (IDictionary events) + { + PreFilterEvents (events); + } + + void IDesignerFilter.PreFilterProperties (IDictionary properties) + { + PreFilterProperties (properties); + } + +#endregion + + +#region ITreeDesigner + // Returns a collection of the designers of the associated components + // + ICollection ITreeDesigner.Children { + get { + ICollection components = this.AssociatedComponents; + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + + if (host != null) { + ArrayList designers = new ArrayList (); + foreach (IComponent component in components) { + IDesigner designer = host.GetDesigner (component); + if (designer != null) + designers.Add (designer); + } + IDesigner[] result = new IDesigner[designers.Count]; + designers.CopyTo (result); + return result; + } + return new IDesigner[0]; + } + } + + IDesigner ITreeDesigner.Parent { + get { + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host != null && this.ParentComponent != null) + return host.GetDesigner (this.ParentComponent); + + return null; + } + } +#endregion + + // Helper method - not an ISerivceProvider + // + protected virtual object GetService (Type service) + { + if (_component != null && _component.Site != null) + return _component.Site.GetService (service); + + return null; + } + + public void Dispose () + { + this.Dispose (true); + GC.SuppressFinalize (this); + } + + + protected virtual void Dispose (bool disposing) + { + if (disposing) + _component = null; + } + + ~ComponentDesigner () + { + this.Dispose (false); + } + } +} diff --git a/source/ShiftUI/Design/ComponentEditorForm.cs b/source/ShiftUI/Design/ComponentEditorForm.cs new file mode 100644 index 0000000..0cd0584 --- /dev/null +++ b/source/ShiftUI/Design/ComponentEditorForm.cs @@ -0,0 +1,96 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004 Novell, Inc. +// +// Authors: +// Dennis Hayes ([email protected]) + +using System; +using System.ComponentModel; +using ShiftUI; +using System.Runtime.InteropServices; + +namespace ShiftUI.Design { + [ToolboxItem (false)] + [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)] + [ComVisible (true)] + public class ComponentEditorForm : Form { + + [MonoTODO] + public ComponentEditorForm(object component, Type[] pageTypes){ + } + + #region Public Properties + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + new public virtual bool AutoSize { + get { return base.AutoSize; } + set { base.AutoSize = value; } + } + #endregion + + [MonoTODO] + protected override void OnActivated(EventArgs e){ + } + + [MonoTODO] + protected virtual void OnSelChangeSelector(object source, TreeViewEventArgs e){ + } + + [MonoTODO] + public override bool PreProcessMessage(ref Message msg){ + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual DialogResult ShowForm(){ + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual DialogResult ShowForm(int page){ + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual DialogResult ShowForm(IWin32Window owner){ + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual DialogResult ShowForm(IWin32Window owner, int page){ + throw new NotImplementedException (); + } + [MonoTODO] + // can't override the function in Widget. bug in compiler. Fixed? + protected override void OnHelpRequested(HelpEventArgs e){ + } + + #region Public Events + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new event EventHandler AutoSizeChanged { + add { base.AutoSizeChanged += value; } + remove { base.AutoSizeChanged -= value; } + } + #endregion + } +} diff --git a/source/ShiftUI/Design/ComponentEditorPage.cs b/source/ShiftUI/Design/ComponentEditorPage.cs new file mode 100644 index 0000000..9b93b9a --- /dev/null +++ b/source/ShiftUI/Design/ComponentEditorPage.cs @@ -0,0 +1,210 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004 Novell, Inc. +// +// Authors: +// Andreas Nahr ([email protected]) +// + +using System.ComponentModel; +using System.Drawing; +using System.Runtime.InteropServices; +using System; + +namespace ShiftUI.Design +{ + [ClassInterfaceAttribute (ClassInterfaceType.AutoDispatch)] + [ComVisible (true)] + public abstract class ComponentEditorPage : Panel + { + private bool commitOnDeactivate = false; + private IComponent component; + private bool firstActivate = true; + private Icon icon; + private int loading = 0; + private bool loadRequired = false; + private IComponentEditorPageSite pageSite; + + public ComponentEditorPage () + { + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + new public virtual bool AutoSize { + get { return base.AutoSize; } + set { base.AutoSize = value; } + } + + public bool CommitOnDeactivate + { + get { return commitOnDeactivate; } + set { commitOnDeactivate = value; } + } + + protected IComponent Component { + get { return component; } + set { component = value; } + } + + [MonoTODO ("Find out what this does.")] + protected override CreateParams CreateParams { + get { + throw new NotImplementedException (); + } + } + + protected bool FirstActivate { + get { return firstActivate; } + set { firstActivate = value; } + } + + public Icon Icon { + get { return icon; } + set { icon = value; } + } + + protected int Loading { + get { return loading; } + set { loading = value; } + } + + protected bool LoadRequired { + get { return loadRequired; } + set { loadRequired = value; } + } + + protected IComponentEditorPageSite PageSite { + get { return pageSite; } + set { pageSite = value; } + } + + public virtual string Title { + get { return base.Text; } + } + + public virtual void Activate () + { + Visible = true; + firstActivate = false; + if (loadRequired) { + EnterLoadingMode (); + LoadComponent (); + ExitLoadingMode (); + } + } + + public virtual void ApplyChanges () + { + SaveComponent (); + } + + public virtual void Deactivate () + { + Visible = false; + } + + protected void EnterLoadingMode () + { + loading++; + } + + protected void ExitLoadingMode () + { + loading--; + } + + public virtual Widget GetWidget () + { + return this; + } + + protected IComponent GetSelectedComponent () + { + return component; + } + + protected bool IsFirstActivate () + { + return firstActivate; + } + + protected bool IsLoading () + { + return (loading != 0); + } + + public virtual bool IsPageMessage (ref Message msg) + { + return PreProcessMessage (ref msg); + } + + protected abstract void LoadComponent (); + + [MonoTODO ("Find out what this does.")] + public virtual void OnApplyComplete () + { + } + + protected virtual void ReloadComponent () + { + loadRequired = true; + } + + protected abstract void SaveComponent (); + + public virtual void SetComponent (IComponent component) + { + this.component = component; + ReloadComponent (); + } + + [MonoTODO ("Find out what this does.")] + protected virtual void SetDirty () + { + } + + public virtual void SetSite (IComponentEditorPageSite site) + { + pageSite = site; + pageSite.GetWidget ().Widgets.Add (this); + + } + + public virtual void ShowHelp () + { + } + + public virtual bool SupportsHelp () + { + return false; + } + + #region Public Events + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new event EventHandler AutoSizeChanged { + add { base.AutoSizeChanged += value; } + remove { base.AutoSizeChanged -= value; } + } + #endregion + } +} diff --git a/source/ShiftUI/Design/ComponentTray.cs b/source/ShiftUI/Design/ComponentTray.cs new file mode 100644 index 0000000..d4c0f93 --- /dev/null +++ b/source/ShiftUI/Design/ComponentTray.cs @@ -0,0 +1,247 @@ +// +// ShiftUI.Design.ComponentTray +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +// STUBS ONLY!!! +// +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; + +namespace ShiftUI.Design +{ + [DesignTimeVisible (false)] + [ToolboxItem (false)] + [ProvideProperty ("Location", typeof (IComponent))] + public class ComponentTray : ScrollableWidget, IExtenderProvider + { + + private IServiceProvider _serviceProvider; + private IDesigner _mainDesigner = null; + private bool _showLargeIcons = false; + private bool _autoArrange = false; + + public ComponentTray (IDesigner mainDesigner, IServiceProvider serviceProvider) + { + if (mainDesigner == null) { + throw new ArgumentNullException ("mainDesigner"); + } + if (serviceProvider == null) { + throw new ArgumentNullException ("serviceProvider"); + } + + _mainDesigner = mainDesigner; + _serviceProvider = serviceProvider; + } + + public bool AutoArrange { + get { return _autoArrange; } + set { _autoArrange = value; } + } + + [MonoTODO] + public int ComponentCount { + get { return 0; } + } + + public bool ShowLargeIcons { + get { return _showLargeIcons; } + set { _showLargeIcons = value; } + } + + + [MonoTODO] + public virtual void AddComponent (IComponent component) + { + } + + protected virtual bool CanCreateComponentFromTool (ToolboxItem tool) + { + return true; + } + + protected virtual bool CanDisplayComponent (IComponent component) + { + return false; + } + + [MonoTODO] + public void CreateComponentFromTool (ToolboxItem tool) + { + } + + [MonoTODO] + protected void DisplayError (Exception e) + { + } + + protected override void Dispose (bool disposing) + { + } + + [Browsable (false)] + [Category ("Layout")] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + [DesignOnly (true)] + [Localizable (false)] + [MonoTODO] + public Point GetLocation (IComponent receiver) + { + return new Point (0,0); + } + + [MonoTODO] + public void SetLocation (IComponent receiver, Point location) + { + } + + [MonoTODO] + public IComponent GetNextComponent (IComponent component, bool forward) + { + throw new NotImplementedException (); + } + + [Browsable (false)] + [Category ("Layout")] + [DesignOnly (true)] + [Localizable (false)] + [MonoTODO] + public Point GetTrayLocation (IComponent receiver) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public bool IsTrayComponent (IComponent comp) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public void SetTrayLocation (IComponent receiver, Point location) + { + throw new NotImplementedException (); + } + + [MonoTODO] + protected override void OnMouseDoubleClick (MouseEventArgs e) + { + } + + [MonoTODO] + protected override void OnDragDrop (DragEventArgs de) + { + } + + [MonoTODO] + protected override void OnDragEnter (DragEventArgs de) + { + } + + [MonoTODO] + protected override void OnDragLeave (EventArgs e) + { + } + + [MonoTODO] + protected override void OnDragOver (DragEventArgs de) + { + } + + [MonoTODO] + protected override void OnGiveFeedback (GiveFeedbackEventArgs gfevent) + { + } + + [MonoTODO] + protected override void OnLayout (LayoutEventArgs levent) + { + } + + [MonoTODO] + protected virtual void OnLostCapture () + { + } + + [MonoTODO] + protected override void OnMouseDown (MouseEventArgs e) + { + } + + [MonoTODO] + protected override void OnMouseMove (MouseEventArgs e) + { + } + + [MonoTODO] + protected override void OnMouseUp (MouseEventArgs e) + { + } + + [MonoTODO] + protected override void OnPaint (PaintEventArgs pe) + { + } + + [MonoTODO] + protected virtual void OnSetCursor () + { + } + + [MonoTODO] + public virtual void RemoveComponent (IComponent component) + { + } + + [MonoTODO] + protected override void WndProc (ref Message m) + { + base.WndProc (ref m); + } + + bool IExtenderProvider.CanExtend (object component) + { + return false; + } + + protected override object GetService (Type service) + { + if (_serviceProvider != null) { + return _serviceProvider.GetService (service); + } + return null; + } + + } +} diff --git a/source/ShiftUI/Design/Consts.cs b/source/ShiftUI/Design/Consts.cs new file mode 100644 index 0000000..ef7fc20 --- /dev/null +++ b/source/ShiftUI/Design/Consts.cs @@ -0,0 +1,100 @@ +// +// Consts.cs +// +// Author: +// Marek Sieradzki ([email protected]) +// +// (C) 2006 Marek Sieradzki +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +#define NET_4_5 +using System; +using System.IO; +using Microsoft.Build.Utilities; + +public static class Consts { + + public static bool RunningOnMono () + { + return Type.GetType ("Mono.Runtime") != null; + } + + public static string BinPath { + get { + if (RunningOnMono ()) { +#if XBUILD_14 + string profile = "xbuild_14"; +#elif XBUILD_12 + string profile = "xbuild_12"; +#elif NET_4_5 + string profile = "net_4_x"; +#else + #error "Unknown profile" +#endif + var corlib = typeof (object).Assembly.Location; + var lib = Path.GetDirectoryName (Path.GetDirectoryName (corlib)); + return Path.Combine (lib, profile); + } else { +#if XBUILD_14 + return ToolLocationHelper.GetPathToBuildTools ("14.0"); +#elif XBUILD_12 + return ToolLocationHelper.GetPathToBuildTools ("12.0"); +#elif NET_4_5 + return ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version45); +#elif NET_4_0 + return ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version40); +#else + return ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version20); +#endif + } + } + } + + public static string ToolsVersionString { + get { +#if XBUILD_14 + return " ToolsVersion='14.0'"; +#elif XBUILD_12 + return " ToolsVersion='12.0'"; +#elif NET_4_0 + return " ToolsVersion='4.0'"; +#else + return String.Empty; +#endif + } + } + + public static string GetTasksAsmPath () + { +#if XBUILD_14 + return Path.Combine (BinPath, "Microsoft.Build.Tasks.Core.dll"); +#elif XBUILD_12 + return Path.Combine (BinPath, "Microsoft.Build.Tasks.v12.0.dll"); +#elif NET_4_0 + return Path.Combine (BinPath, "Microsoft.Build.Tasks.v4.0.dll"); +#else + return Path.Combine (BinPath, "Microsoft.Build.Tasks.dll"); +#endif + } + + public const string AssemblySystem_Drawing = "System.Drawing"; + public const string AssemblySystem_Design = "System.Design"; + public const string AssemblySystem_Windows_Forms = "ShiftUI"; +} diff --git a/source/ShiftUI/Design/ControlDataObject.cs b/source/ShiftUI/Design/ControlDataObject.cs new file mode 100644 index 0000000..932a4de --- /dev/null +++ b/source/ShiftUI/Design/ControlDataObject.cs @@ -0,0 +1,120 @@ +using System; +using ShiftUI; + +namespace ShiftUI.Design +{ + // A IDataObject that supports Widget and Widget[] format + // + internal class WidgetDataObject : IDataObject + { + private object _data = null; + private string _format = null; + + public WidgetDataObject () + { + _data = null; + _format = null; + } + + public WidgetDataObject (Widget control) + { + SetData (control); + } + + public WidgetDataObject (Widget[] controls) + { + SetData (controls); + } + + public object GetData (Type format) + { + return this.GetData (format.ToString ()); + } + + public object GetData (string format) + { + return this.GetData (format, true); + } + + public object GetData (string format, bool autoConvert) + { + if (format == _format) { + return _data; + } + return null; + } + + public bool GetDataPresent (Type format) + { + return this.GetDataPresent (format.ToString()); + } + + public bool GetDataPresent (string format) + { + return this.GetDataPresent (format, true); + } + + public bool GetDataPresent (string format, bool autoConvert) + { + if (format == _format) { + return true; + } + return false; + } + + public string[] GetFormats () + { + return this.GetFormats (true); + } + + public string[] GetFormats (bool autoConvert) + { + string[] formats = new string[2]; + formats[0] = typeof (Widget).ToString (); + formats[1] = typeof (Widget[]).ToString (); + return formats; + } + + public void SetData (object data) + { + if (data is Widget) + this.SetData (typeof (Widget), data); + else if (data is Widget[]) + this.SetData (typeof (Widget[]), data); + } + + public void SetData (Type format, object data) + { + this.SetData (format.ToString (), data); + } + + public void SetData (string format, object data) + { + this.SetData (format, true, data); + } + + public void SetData (string format, bool autoConvert, object data) + { + if (ValidateFormat (format)) { + _data = data; + _format = format; + } + } + + private bool ValidateFormat (string format) + { + bool valid = false; + + string[] formats = GetFormats (); + foreach (string f in formats) { + if (f == format) { + valid = true; + break; + } + } + + return valid; + } + } +} + diff --git a/source/ShiftUI/Design/ControlDesigner.cs b/source/ShiftUI/Design/ControlDesigner.cs new file mode 100644 index 0000000..e241f08 --- /dev/null +++ b/source/ShiftUI/Design/ControlDesigner.cs @@ -0,0 +1,974 @@ +// +// ShiftUI.Design.WidgetDesigner +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Runtime.InteropServices; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; +using ShiftUI.Design.Behavior; + +namespace ShiftUI.Design +{ + public class WidgetDesigner : ComponentDesigner, IMessageReceiver + { + + + private WndProcRouter _messageRouter; + private bool _locked = false; + private bool _mouseDown = false; + private bool _mouseMoveAfterMouseDown = false; + private bool _mouseDownFirstMove = false; + private bool _firstMouseMoveInClient = true; + + public WidgetDesigner () + { + } + +#region Initialization + public override void Initialize (IComponent component) + { + base.Initialize (component); + + if (!(component is Widget)) + throw new ArgumentException ("Component is not a Widget."); + + Widget.Text = component.Site.Name; + _messageRouter = new WndProcRouter ((Widget) component, (IMessageReceiver) this); + Widget.WindowTarget = _messageRouter; + + // DT properties + // + this.Visible = true; + this.Enabled = true; + this.Locked = false; + this.AllowDrop = false; + // + // The control properties + // + Widget.Enabled = true; + Widget.Visible = true; + Widget.AllowDrop = false; + + this.Widget.DragDrop += new DragEventHandler (OnDragDrop); + this.Widget.DragEnter += new DragEventHandler (OnDragEnter); + this.Widget.DragLeave += new EventHandler (OnDragLeave); + this.Widget.DragOver += new DragEventHandler (OnDragOver); + + // XXX: The control already has a handle? + // + if (Widget.IsHandleCreated) + OnCreateHandle (); + + } + + // The default implementation of this method sets the component's Text property to + // its name (Component.Site.Name), if the property field is of type string. + // + public override void OnSetComponentDefaults () + { + if (this.Component != null && this.Component.Site != null) { + PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties (this.Component)["Text"]; + if (propertyDescriptor != null && !propertyDescriptor.IsReadOnly && + propertyDescriptor.PropertyType == typeof (string)) { + propertyDescriptor.SetValue (Component, Component.Site.Name); + } + } + } +#endregion + + +#region Properties and Fields - AccessabilityObject Left + protected static readonly Point InvalidPoint = new Point (int.MinValue, int.MinValue); + + protected internal BehaviorService BehaviorService { + get { throw new NotImplementedException (); } + } + + public virtual Widget Widget { + get { return (Widget) base.Component; } + } + + protected virtual bool EnableDragRect { + get { return true; } + } + + public virtual SelectionRules SelectionRules { + get { + if (this.Widget == null) + return SelectionRules.None; + + // all controls on the surface are visible + // + SelectionRules selectionRules = SelectionRules.Visible; + + if ((bool)GetValue (this.Component, "Locked") == true) { + selectionRules |= SelectionRules.Locked; + } + else { + DockStyle dockStyle = (DockStyle) this.GetValue (base.Component, "Dock", typeof (DockStyle)); + + switch (dockStyle) { + case DockStyle.Top: + selectionRules |= SelectionRules.BottomSizeable; + break; + case DockStyle.Left: + selectionRules |= SelectionRules.RightSizeable; + break; + case DockStyle.Right: + selectionRules |= SelectionRules.LeftSizeable; + break; + case DockStyle.Bottom: + selectionRules |= SelectionRules.TopSizeable; + break; + case DockStyle.Fill: + break; + default: + selectionRules |= SelectionRules.Moveable; + selectionRules |= SelectionRules.AllSizeable; + break; + } + } + + return selectionRules; + } + } + + public override ICollection AssociatedComponents { + get { + ArrayList components = new ArrayList (); + foreach (Widget c in this.Widget.Widgets) + if (c.Site != null) + components.Add (c); + return components; + } + } + + protected override IComponent ParentComponent { + get { return this.GetValue (this.Widget, "Parent") as Widget;} + } + // TODO: implement WidgetDesigner.WidgetAccessabilityObject + // + public virtual AccessibleObject AccessibilityObject { + get { + if (accessibilityObj == null) + accessibilityObj = new AccessibleObject (); + + return accessibilityObj; + } + } + protected AccessibleObject accessibilityObj; + +#endregion + + +#region WndProc + + protected void DefWndProc (ref Message m) + { + _messageRouter.ToWidget (ref m); + } + + protected void BaseWndProc (ref Message m) + { + _messageRouter.ToSystem (ref m); + } + + void IMessageReceiver.WndProc (ref Message m) + { + this.WndProc (ref m); + } + + // Keep in mind that messages are recieved for the child controls if routed + // + protected virtual void WndProc (ref Message m) + { + // Filter out kb input + // + if ((Native.Msg) m.Msg >= Native.Msg.WM_KEYFIRST && (Native.Msg) m.Msg <= Native.Msg.WM_KEYLAST) + return; + + // Mouse messages should be routed the control, if GetHitTest (virtual) returns true. + // + if (IsMouseMessage ((Native.Msg) m.Msg) && + this.GetHitTest (new Point (Native.LoWord((int) m.LParam), Native.HiWord (((int) m.LParam))))) { + + this.DefWndProc (ref m); + return; + } + + switch ((Native.Msg) m.Msg) { + case Native.Msg.WM_CREATE: + this.DefWndProc (ref m); + if (m.HWnd == this.Widget.Handle) + OnCreateHandle (); + break; + + case Native.Msg.WM_CONTEXTMENU: + break; + + case Native.Msg.WM_SETCURSOR: + if (this.GetHitTest (new Point (Native.LoWord ((int) m.LParam), Native.HiWord ((int) m.LParam)))) + this.DefWndProc (ref m); + else + OnSetCursor (); + break; + + case Native.Msg.WM_SETFOCUS: + this.DefWndProc (ref m); + break; + + case Native.Msg.WM_PAINT: + // Wait for control's WM_PAINT to complete first. + // + this.DefWndProc (ref m); + + Graphics gfx = Graphics.FromHwnd (m.HWnd); + PaintEventArgs args = new PaintEventArgs (gfx, this.Widget.Bounds); + OnPaintAdornments (args); + gfx.Dispose (); + args.Dispose (); + break; + + case Native.Msg.WM_NCRBUTTONDOWN: + case Native.Msg.WM_NCLBUTTONDOWN: + case Native.Msg.WM_NCMBUTTONDOWN: + case Native.Msg.WM_NCLBUTTONDBLCLK: + case Native.Msg.WM_NCRBUTTONDBLCLK: + break; + + case Native.Msg.WM_LBUTTONDBLCLK: + case Native.Msg.WM_RBUTTONDBLCLK: + case Native.Msg.WM_MBUTTONDBLCLK: + if ((Native.Msg)m.Msg == Native.Msg.WM_LBUTTONDBLCLK) + _mouseButtonDown = MouseButtons.Left; + else if ((Native.Msg)m.Msg == Native.Msg.WM_RBUTTONDBLCLK) + _mouseButtonDown = MouseButtons.Right; + else if ((Native.Msg)m.Msg == Native.Msg.WM_MBUTTONDBLCLK) + _mouseButtonDown = MouseButtons.Middle; + OnMouseDoubleClick (); + this.BaseWndProc (ref m); + break; + + case Native.Msg.WM_MOUSEHOVER: + OnMouseHover (); + break; + + case Native.Msg.WM_LBUTTONDOWN: + case Native.Msg.WM_RBUTTONDOWN: + case Native.Msg.WM_MBUTTONDOWN: + _mouseMoveAfterMouseDown = true; + if ((Native.Msg)m.Msg == Native.Msg.WM_LBUTTONDOWN) + _mouseButtonDown = MouseButtons.Left; + else if ((Native.Msg)m.Msg == Native.Msg.WM_RBUTTONDOWN) + _mouseButtonDown = MouseButtons.Right; + else if ((Native.Msg)m.Msg == Native.Msg.WM_MBUTTONDOWN) + _mouseButtonDown = MouseButtons.Middle; + + if (_firstMouseMoveInClient) { + OnMouseEnter (); + _firstMouseMoveInClient = false; + } + this.OnMouseDown (Native.LoWord ((int)m.LParam), Native.HiWord ((int)m.LParam)); + this.BaseWndProc (ref m); + break; + + case Native.Msg.WM_MOUSELEAVE: + _firstMouseMoveInClient = false; + OnMouseLeave (); + this.BaseWndProc (ref m); + break; + + // The WM_CANCELMODE message is sent to cancel certain modes, such as mouse capture. + // For example, the system sends this message to the active window when a dialog box + // or message box is displayed. Certain functions also send this message explicitly to + // the specified window regardless of whether it is the active window. For example, + // the EnableWindow function sends this message when disabling the specified window. + // + case Native.Msg.WM_CANCELMODE: + OnMouseDragEnd (true); + this.DefWndProc (ref m); + break; + + case Native.Msg.WM_LBUTTONUP: + case Native.Msg.WM_RBUTTONUP: + case Native.Msg.WM_NCLBUTTONUP: + case Native.Msg.WM_NCRBUTTONUP: + case Native.Msg.WM_MBUTTONUP: + case Native.Msg.WM_NCMBUTTONUP: + _mouseMoveAfterMouseDown = false; // just in case + this.OnMouseUp (); + this.BaseWndProc (ref m); + break; + + // // MWF Specific msg! - must reach control + // // + // case Native.Msg.WM_MOUSE_ENTER: + // _firstMouseMoveInClient = false; // just so that nothing will get fired in WM_MOUSEMOVE + // OnMouseEnter (); + // this.DefWndProc (ref m); + // break; + + // FIXME: The first MOUSEMOVE after WM_MOUSEDOWN should be ingored + // + case Native.Msg.WM_MOUSEMOVE: + if (_mouseMoveAfterMouseDown) { // mousemove is send after each mousedown so ignore that + _mouseMoveAfterMouseDown = false; + this.BaseWndProc (ref m); + return; + } + // If selection is in progress pass the mouse move msg to the primary selection. + // If resizing is in progress pass to the parent of the primary selection (remmember that the selection + // frame is not a control and is drawn in the parent of the primary selection). + // + // Required in order for those 2 operations to continue when the mouse is moving over a control covering + // the one where the action takes place. + // + IUISelectionService uiSelectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + ISelectionService selectionServ = this.GetService (typeof (ISelectionService)) as ISelectionService; + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + + + if (uiSelectionServ != null && selectionServ != null && host != null) { + Widget primarySelection = selectionServ.PrimarySelection as Widget; + Point location = new Point (Native.LoWord ((int)m.LParam), Native.HiWord ((int)m.LParam)); + + if (uiSelectionServ.SelectionInProgress && + this.Component != host.RootComponent && + this.Component != selectionServ.PrimarySelection) { + + location = primarySelection.PointToClient (this.Widget.PointToScreen (location)); + Native.SendMessage (primarySelection.Handle, (Native.Msg)m.Msg, m.WParam, Native.LParam (location.X, location.Y)); + } + else if (uiSelectionServ.ResizeInProgress && + // this.Component != host.RootComponent && + this.Widget.Parent == ((Widget)selectionServ.PrimarySelection).Parent) { + + location = this.Widget.Parent.PointToClient (this.Widget.PointToScreen (location)); + Native.SendMessage (this.Widget.Parent.Handle, (Native.Msg)m.Msg, m.WParam, Native.LParam (location.X, location.Y)); + } + else { + this.OnMouseMove (location.X, location.Y); + } + } + else { + this.OnMouseMove (Native.LoWord ((int)m.LParam), Native.HiWord ((int)m.LParam)); + } + this.BaseWndProc (ref m); + break; + + default: + // Pass everything else to the control and return + // + this.DefWndProc (ref m); + break; + } + } + + // Indicates whether a mouse click at the specified point should be handled by the control. + // + protected virtual bool GetHitTest (Point point) + { + return false; + } + + private bool IsMouseMessage (Native.Msg msg) + { + if (msg >= Native.Msg.WM_MOUSEFIRST && msg <= Native.Msg.WM_MOUSELAST) + return true; + else if (msg >= Native.Msg.WM_NCLBUTTONDOWN && msg <= Native.Msg.WM_NCMBUTTONDBLCLK) + return true; + else if (msg == Native.Msg.WM_MOUSEHOVER || msg == Native.Msg.WM_MOUSELEAVE) + return true; + else + return false; + } +#endregion + + +#region WndProc Message Handlers + + protected virtual void OnSetCursor () + { + } + + // Raises the DoDefaultAction. + // + private void OnMouseDoubleClick () + { + try { + base.DoDefaultAction (); + } + catch (Exception e) { + this.DisplayError (e); + } + } + + internal virtual void OnMouseDown (int x, int y) + { + _mouseDown = true; + _mouseDownFirstMove = true; + IUISelectionService uiSelection = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (uiSelection != null && uiSelection.AdornmentsHitTest (this.Widget, x, y)) { + // 1) prevent primary selection from being changed at this point. + // 2) delegate behaviour in the future to the IUISelectionService + } + else { + ISelectionService selectionService = this.GetService (typeof (ISelectionService)) as ISelectionService; + if (selectionService != null) { + selectionService.SetSelectedComponents (new IComponent[] { this.Component }); + } + } + } + + // Note that this is a pure WM_MOUSEMOVE acceptor + // + internal virtual void OnMouseMove (int x, int y) + { + if (_mouseDown) { + if (_mouseDownFirstMove) { + OnMouseDragBegin (x, y); + _mouseDownFirstMove = false; + } + else { + OnMouseDragMove (x, y); + } + } + + } + + internal virtual void OnMouseUp () + { + IUISelectionService uiSelection = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + + if (_mouseDown) { + this.OnMouseDragEnd (false); + if (uiSelection != null && (uiSelection.SelectionInProgress || uiSelection.ResizeInProgress)) { + uiSelection.MouseDragEnd (false); + } + _mouseDown = false; + } + else { + if (uiSelection != null && (uiSelection.SelectionInProgress || uiSelection.ResizeInProgress)) { + // If the mouse up happens over the a control which is not defacto participating in + // the selection or resizing in progress, then inform the IUISelectionService of that event + // + uiSelection.MouseDragEnd (false); + } + } + } + + protected virtual void OnMouseEnter () + { + } + + protected virtual void OnMouseHover () + { + } + + protected virtual void OnMouseLeave () + { + } + + // Provides an opportunity to perform additional processing immediately + // after the control handle has been created. + // + protected virtual void OnCreateHandle () + { + } + + // Called after the control is done with the painting so that the designer host + // can paint stuff over it. + // + protected virtual void OnPaintAdornments (PaintEventArgs pe) + { + } +#endregion + + +#region Mouse Dragging + + MouseButtons _mouseButtonDown; + + internal MouseButtons MouseButtonDown { + get { return _mouseButtonDown; } + } + + protected virtual void OnMouseDragBegin (int x, int y) + { + IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null && ((this.SelectionRules & SelectionRules.Moveable) == SelectionRules.Moveable)) { + // once this is fired the parent control (parentcontroldesigner) will start getting dragover events. + // + selectionServ.DragBegin (); + } + } + + protected virtual void OnMouseDragMove (int x, int y) + { + } + + protected virtual void OnMouseDragEnd (bool cancel) + { + } +#endregion + + +#region Parenting + protected void HookChildWidgets (Widget firstWidget) + { + if (firstWidget != null) { + foreach (Widget control in firstWidget.Widgets) { + control.WindowTarget = (IWindowTarget) new WndProcRouter (control, (IMessageReceiver) this); + } + } + } + + protected void UnhookChildWidgets (Widget firstWidget) + { + if (firstWidget != null) { + foreach (Widget control in firstWidget.Widgets) { + if (control.WindowTarget is WndProcRouter) + ((WndProcRouter) control.WindowTarget).Dispose (); + } + } + } + + // Someone please tell me why the hell is this method here? + // What about having ParentWidgetDesigner.CanParent(...) ? + // + public virtual bool CanBeParentedTo (IDesigner parentDesigner) + { + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + + if (parentDesigner is ParentWidgetDesigner && + this.Component != host.RootComponent && + !this.Widget.Widgets.Contains (((ParentWidgetDesigner)parentDesigner).Widget)) { + return true; + } else { + return false; + } + } +#endregion + + protected void DisplayError (Exception e) + { + if (e != null) { + IUIService uiService = GetService (typeof (IUIService)) as IUIService; + if (uiService != null) { + uiService.ShowError (e); + } + else { + string errorText = e.Message; + if (errorText == null || errorText == String.Empty) + errorText = e.ToString (); + MessageBox.Show (errorText, "Error"); + } + } + } + +#region Drag and Drop handling + + // Enables or disables Drag and Drop + // + protected void EnableDragDrop(bool value) + { + if (this.Widget != null) { + if (value) { + Widget.DragDrop += new DragEventHandler (OnDragDrop); + Widget.DragOver += new DragEventHandler (OnDragOver); + Widget.DragEnter += new DragEventHandler (OnDragEnter); + Widget.DragLeave += new EventHandler (OnDragLeave); + Widget.GiveFeedback += new GiveFeedbackEventHandler (OnGiveFeedback); + Widget.AllowDrop = true; + } + else { + Widget.DragDrop -= new DragEventHandler (OnDragDrop); + Widget.DragOver -= new DragEventHandler (OnDragOver); + Widget.DragEnter -= new DragEventHandler (OnDragEnter); + Widget.DragLeave -= new EventHandler (OnDragLeave); + Widget.GiveFeedback -= new GiveFeedbackEventHandler (OnGiveFeedback); + Widget.AllowDrop = false; + } + } + } + + private void OnGiveFeedback (object sender, GiveFeedbackEventArgs e) + { + OnGiveFeedback (e); + } + + private void OnDragDrop (object sender, DragEventArgs e) + { + OnDragDrop (e); + } + + private void OnDragEnter (object sender, DragEventArgs e) + { + OnDragEnter (e); + } + + private void OnDragLeave (object sender, EventArgs e) + { + OnDragLeave (e); + } + + private void OnDragOver (object sender, DragEventArgs e) + { + OnDragOver (e); + } + + protected virtual void OnGiveFeedback (GiveFeedbackEventArgs e) + { + e.UseDefaultCursors = false; + } + + protected virtual void OnDragDrop (DragEventArgs e) + { + } + + protected virtual void OnDragEnter (DragEventArgs e) + { + } + + protected virtual void OnDragLeave (EventArgs e) + { + } + + protected virtual void OnDragOver (DragEventArgs e) + { + } +#endregion + + +#region Redirected Properties + + // This IDesignerFilter interface method override adds a set of properties + // to this designer's component at design time. This method adds the following + // browsable properties: "Visible", "Enabled", "ContextMenu", "AllowDrop", "Location", + // "Name", "Widgets", and "Locked". + // + // XXX: We aren't redirecting Widgets + // + protected override void PreFilterProperties (IDictionary properties) + { + base.PreFilterProperties (properties); + + string[] newProperties = { + "Visible", "Enabled", "ContextMenu", "AllowDrop", "Location", "Name", + }; + + Attribute[][] attributes = { + new Attribute[] { new DefaultValueAttribute (true) }, + new Attribute[] { new DefaultValueAttribute (true) }, + new Attribute[] { new DefaultValueAttribute (null) }, + new Attribute[] { new DefaultValueAttribute (false) }, + new Attribute[] { new DefaultValueAttribute (typeof (Point), "0, 0") }, + new Attribute[] {} + }; + + PropertyDescriptor propertyDescriptor = null; + + // If existing redirect each property to the WidgetDesigner. + // + for (int i=0; i < newProperties.Length; i++) { + propertyDescriptor = properties[newProperties[i]] as PropertyDescriptor; + if (propertyDescriptor != null) + properties[newProperties[i]] = TypeDescriptor.CreateProperty (typeof (WidgetDesigner), + propertyDescriptor, + attributes[i]); + } + + // This one is a must to have. + // + properties["Locked"] = TypeDescriptor.CreateProperty (typeof (WidgetDesigner), "Locked", + typeof(bool), + new Attribute[] { + DesignOnlyAttribute.Yes, + BrowsableAttribute.Yes, + CategoryAttribute.Design, + new DefaultValueAttribute (false), + new DescriptionAttribute("The Locked property determines if we can move or resize the control.") + }); + + } + + // ShadowProperties returns the real property value if there is no "shadow" one set + // Welcome to the land of shadows... :-) + // + private bool Visible { + get { return (bool) base.ShadowProperties["Visible"]; } + set { base.ShadowProperties["Visible"] = value; } + } + + private bool Enabled { + get { return (bool) base.ShadowProperties["Enabled"]; } + set { base.ShadowProperties["Enabled"] = value; } + } + + private bool Locked { + get { return _locked; } + set { _locked = value; } + } + + private bool AllowDrop { + get { return (bool)base.ShadowProperties["AllowDrop"]; } + set { base.ShadowProperties["AllowDrop"] = value; } + } + + private string Name { + get { return base.Component.Site.Name; } + set { base.Component.Site.Name = value; } + } + + private Point Location { + get { return this.Widget.Location; } + set { this.Widget.Location = value; } + } +#endregion + + +#region Utility methods + internal object GetValue (object component, string propertyName) + { + return this.GetValue (component, propertyName, null); + } + + internal object GetValue (object component, string propertyName, Type propertyType) + { + PropertyDescriptor prop = TypeDescriptor.GetProperties (component)[propertyName] as PropertyDescriptor; + if (prop == null) + throw new InvalidOperationException ("Property \"" + propertyName + "\" is missing on " + + component.GetType().AssemblyQualifiedName); + if (propertyType != null && !propertyType.IsAssignableFrom (prop.PropertyType)) + throw new InvalidOperationException ("Types do not match: " + prop.PropertyType.AssemblyQualifiedName + + " : " + propertyType.AssemblyQualifiedName); + return prop.GetValue (component); + } + + internal void SetValue (object component, string propertyName, object value) + { + PropertyDescriptor prop = TypeDescriptor.GetProperties (component)[propertyName] as PropertyDescriptor; + + if (prop == null) + throw new InvalidOperationException ("Property \"" + propertyName + "\" is missing on " + + component.GetType().AssemblyQualifiedName); + if (!prop.PropertyType.IsAssignableFrom (value.GetType ())) + throw new InvalidOperationException ("Types do not match: " + value.GetType ().AssemblyQualifiedName + + " : " + prop.PropertyType.AssemblyQualifiedName); + if (!prop.IsReadOnly) + prop.SetValue (component, value); + } +#endregion + + protected override void Dispose (bool disposing) + { + if (disposing) { + if (this.Widget != null) { + UnhookChildWidgets (Widget); + OnMouseDragEnd (true); + _messageRouter.Dispose (); + this.Widget.DragDrop -= new DragEventHandler (OnDragDrop); + this.Widget.DragEnter -= new DragEventHandler (OnDragEnter); + this.Widget.DragLeave -= new EventHandler (OnDragLeave); + this.Widget.DragOver -= new DragEventHandler (OnDragOver); + } + } + base.Dispose (true); + } + + + + public virtual WidgetDesigner InternalWidgetDesigner (int internalWidgetIndex) + { + return null; + } + + public virtual int NumberOfInternalWidgetDesigners () + { + return 0; + } + + protected bool EnableDesignMode (Widget child, string name) + { + if (name == null) + throw new ArgumentNullException ("name"); + if (child == null) + throw new ArgumentNullException ("child"); + + bool success = false; + INestedContainer nestedContainer = this.GetService (typeof (INestedContainer)) as INestedContainer; + if (nestedContainer != null) { + nestedContainer.Add (child, name); + success = true; + } + return success; + } + +#region NET_2_0 Stubs + + [ComVisible (true)] + public class WidgetDesignerAccessibleObject : AccessibleObject + { + [MonoTODO] + public WidgetDesignerAccessibleObject (WidgetDesigner designer, Widget control) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override AccessibleObject GetChild (int index) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override int GetChildCount () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override AccessibleObject GetFocused () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override AccessibleObject GetSelected () + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override AccessibleObject HitTest (int x, int y) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override Rectangle Bounds { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override string DefaultAction { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override string Description { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override string Name { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override AccessibleObject Parent { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override AccessibleRole Role { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override AccessibleStates State { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public override string Value { + get { throw new NotImplementedException (); } + } + } + + [MonoTODO] + protected virtual WidgetBodyGlyph GetWidgetGlyph (GlyphSelectionType selectionType) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public virtual GlyphCollection GetGlyphs (GlyphSelectionType selectionType) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override void InitializeExistingComponent (IDictionary defaultValues) + { + throw new NotImplementedException (); + } + + [MonoTODO] + public override void InitializeNewComponent (IDictionary defaultValues) + { + throw new NotImplementedException (); + } + + [MonoTODO] + protected virtual void OnDragComplete (DragEventArgs de) + { + throw new NotImplementedException (); + } + + [MonoTODO] + protected override InheritanceAttribute InheritanceAttribute { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public virtual IList SnapLines { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public virtual bool ParticipatesWithSnapLines { + get { throw new NotImplementedException (); } + } + + [MonoTODO] + public bool AutoResizeHandles { + get { throw new NotImplementedException (); } + set { throw new NotImplementedException (); } + } +#endregion + + + } +} diff --git a/source/ShiftUI/Design/DefaultMenuCommands.cs b/source/ShiftUI/Design/DefaultMenuCommands.cs new file mode 100644 index 0000000..8284d82 --- /dev/null +++ b/source/ShiftUI/Design/DefaultMenuCommands.cs @@ -0,0 +1,274 @@ +// +// System.ComponentModel.Design.DefaultMenuCommands.cs +// +// Author: +// Ivan N. Zlatev <[email protected]> +// +// (C) 2008 Ivan N. Zlatev +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.ComponentModel.Design.Serialization; +using System.Runtime.Serialization.Formatters.Binary; +using System.Runtime.InteropServices; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; +using System.IO; +using ShiftUI.Design; + +namespace ShiftUI +{ + internal sealed class DefaultMenuCommands + { + private IServiceProvider _serviceProvider; + private const string DT_DATA_FORMAT = "DT_DATA_FORMAT"; + + public DefaultMenuCommands (IServiceProvider serviceProvider) + { + if (serviceProvider == null) + throw new ArgumentNullException ("serviceProvider"); + _serviceProvider = serviceProvider; + } + + public void AddTo (IMenuCommandService commands) + { + commands.AddCommand (new MenuCommand (Copy, StandardCommands.Copy)); + commands.AddCommand (new MenuCommand (Cut, StandardCommands.Cut)); + commands.AddCommand (new MenuCommand (Paste, StandardCommands.Paste)); + commands.AddCommand (new MenuCommand (Delete, StandardCommands.Delete)); + commands.AddCommand (new MenuCommand (SelectAll, StandardCommands.SelectAll)); + } + + private object _clipboard = null; + + private void Copy (object sender, EventArgs args) + { + IDesignerSerializationService stateSerializer = GetService (typeof (IDesignerSerializationService)) as IDesignerSerializationService; + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + ISelectionService selection = GetService (typeof (ISelectionService)) as ISelectionService; + if (host == null || stateSerializer == null || selection == null) + return; + + // copy selected components and their associated components + ICollection selectedComponents = selection.GetSelectedComponents (); + ArrayList toCopy = new ArrayList (); + foreach (object component in selectedComponents) { + if (component == host.RootComponent) + continue; + toCopy.Add (component); + Design.ComponentDesigner designer = host.GetDesigner ((IComponent)component) as Design.ComponentDesigner; + if (designer != null && designer.AssociatedComponents != null) + toCopy.AddRange (designer.AssociatedComponents); + } + object stateData = stateSerializer.Serialize (toCopy); + _clipboard = stateData; + // Console.WriteLine ("Copied components: "); + // foreach (object c in toCopy) + // Console.WriteLine (((IComponent)c).Site.Name); + // + + // TODO: MWF X11 doesn't seem to support custom clipboard formats - bug #357642 + // + // MemoryStream stream = new MemoryStream (); + // new BinaryFormatter().Serialize (stream, stateData); + // stream.Seek (0, SeekOrigin.Begin); + // byte[] serializedData = stream.GetBuffer (); + // Clipboard.SetDataObject (new DataObject (DT_DATA_FORMAT, serializedData)); + } + + // Reminder: We set control.Parent so that it gets serialized for Undo/Redo + // + private void Paste (object sender, EventArgs args) + { + IDesignerSerializationService stateSerializer = GetService (typeof (IDesignerSerializationService)) as IDesignerSerializationService; + ISelectionService selection = GetService (typeof (ISelectionService)) as ISelectionService; + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + IComponentChangeService changeService = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + if (host == null || stateSerializer == null) + return; + // + // TODO: MWF X11 doesn't seem to support custom clipboard formats - bug #357642 + // + // IDataObject dataObject = Clipboard.GetDataObject (); + // byte[] data = dataObject == null ? null : dataObject.GetData (DT_DATA_FORMAT) as byte[]; + // if (data != null) { + // MemoryStream stream = new MemoryStream (data); + // stateSerializer.Deserialize (new BinaryFormatter().Deserialize (stream)); + // ..... + // } + // + if (_clipboard == null) + return; + + DesignerTransaction transaction = host.CreateTransaction ("Paste"); + ICollection components = stateSerializer.Deserialize (_clipboard); + // Console.WriteLine ("Pasted components: "); + // foreach (object c in components) + // Console.WriteLine (((IComponent)c).Site.Name); + foreach (object component in components) { + Widget control = component as Widget; + if (control == null) + continue; // pure Components are added to the ComponentTray by the DocumentDesigner + + PropertyDescriptor parentProperty = TypeDescriptor.GetProperties (control)["Parent"]; + if (control.Parent != null) { + // Already parented during deserialization? + // In that case explicitly raise component changing/ed for the Parent property, + // so it get's cought by the UndoEngine + if (changeService != null) { + changeService.OnComponentChanging (control, parentProperty); + changeService.OnComponentChanged (control, parentProperty, null, control.Parent); + } + } else { + ParentWidgetDesigner parentDesigner = null; + if (selection != null && selection.PrimarySelection != null) + parentDesigner = host.GetDesigner ((IComponent)selection.PrimarySelection) as ParentWidgetDesigner; + if (parentDesigner == null) + parentDesigner = host.GetDesigner (host.RootComponent) as DocumentDesigner; + if (parentDesigner != null && parentDesigner.CanParent (control)) + parentProperty.SetValue (control, parentDesigner.Widget); + } + } + _clipboard = null; + transaction.Commit (); + ((IDisposable)transaction).Dispose (); + } + + private void Cut (object sender, EventArgs args) + { + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host == null) + return; + using (DesignerTransaction transaction = host.CreateTransaction ("Cut")) { + Copy (this, EventArgs.Empty); + Delete (this, EventArgs.Empty); + transaction.Commit (); + } + } + + private void Delete (object sender, EventArgs args) + { + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + ISelectionService selection = GetService (typeof (ISelectionService)) as ISelectionService; + if (host == null || selection == null) + return; + + ICollection selectedComponents = selection.GetSelectedComponents (); + string description = "Delete " + + (selectedComponents.Count > 1 ? (selectedComponents.Count.ToString () + " controls") : + ((IComponent)selection.PrimarySelection).Site.Name); + DesignerTransaction transaction = host.CreateTransaction (description); + + foreach (object component in selectedComponents) { + if (component != host.RootComponent) { + Design.ComponentDesigner designer = host.GetDesigner ((IComponent)component) as Design.ComponentDesigner; + if (designer != null && designer.AssociatedComponents != null) { + foreach (object associatedComponent in designer.AssociatedComponents) + host.DestroyComponent ((IComponent)associatedComponent); + } + host.DestroyComponent ((IComponent)component); + } + } + selection.SetSelectedComponents (selectedComponents, SelectionTypes.Remove); + transaction.Commit (); + } + + private void SelectAll (object sender, EventArgs args) + { + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + ISelectionService selection = GetService (typeof (ISelectionService)) as ISelectionService; + if (host != null && selection != null) + selection.SetSelectedComponents (host.Container.Components, SelectionTypes.Replace); + } + + // * StandardCommands + // o AlignBottom + // o AlignHorizontalCenters + // o AlignLeft + // o AlignRight + // o AlignToGrid + // o AlignTop + // o AlignVerticalCenters + // o BringToFront + // o CenterHorizontally + // o CenterVertically + // -o Copy + // -o Cut + // -o Delete + // o HorizSpaceConcatenate + // o HorizSpaceDecrease + // o HorizSpaceIncrease + // o HorizSpaceMakeEqual + // -o Paste + // -o SelectAll + // o SendToBack + // o SizeToWidget + // o SizeToWidgetHeight + // o SizeToWidgetWidth + // o SizeToGrid + // o SnapToGrid + // o TabOrder + // o VertSpaceConcatenate + // o VertSpaceDecrease + // o VertSpaceIncrease + // o VertSpaceMakeEqual + // o ShowGrid + // o LockWidgets + // + // * MenuCommands + // o KeyDefaultAction + // o KeySelectNext + // o KeySelectPrevious + // o KeyMoveLeft + // o KeySizeWidthDecrease + // o KeyMoveRight + // o KeySizeWidthIncrease + // o KeyMoveUp + // o KeySizeHeightIncrease + // o KeyMoveDown + // o KeySizeHeightDecrease + // o KeyCancel + // o KeyNudgeLeft + // o KeyNudgeDown + // o KeyNudgeRight + // o KeyNudgeUp + // o KeyNudgeHeightIncrease + // o KeyNudgeHeightDecrease + // o KeyNudgeWidthDecrease + // o KeyNudgeWidthIncrease + // o DesignerProperties + // o KeyReverseCancel + + private object GetService (Type serviceType) + { + if (_serviceProvider != null) + return _serviceProvider.GetService (serviceType); + return null; + } + } +} diff --git a/source/ShiftUI/Design/DocumentDesigner.cs b/source/ShiftUI/Design/DocumentDesigner.cs new file mode 100644 index 0000000..e132b1d --- /dev/null +++ b/source/ShiftUI/Design/DocumentDesigner.cs @@ -0,0 +1,485 @@ +// +// ShiftUI.Design.DocumentDesigner +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; +using ShiftUI.Design.Behavior; + +namespace ShiftUI.Design +{ + [ToolboxItemFilter ("ShiftUI")] + public class DocumentDesigner : ScrollableWidgetDesigner, IRootDesigner, IToolboxUser + { + + // This is what you *see* + /* + .-------------------------------------. + | Panel to host the designed Widget | + |--------------Splitter---------------| + | Panel with a ComponentTray | + |_____________________________________| + + */ + // +#region DesignerViewFrame + public class DesignerViewFrame : ShiftUI.UserWidget + { + private ShiftUI.Panel DesignerPanel; + private ShiftUI.Splitter splitter1; + private ShiftUI.Panel ComponentTrayPanel; + private ComponentTray _componentTray; + private Widget _designedWidget; + + public DesignerViewFrame (Widget designedWidget, ComponentTray tray) + { + if (designedWidget == null) { + throw new ArgumentNullException ("designedWidget"); + } + if (tray == null) { + throw new ArgumentNullException ("tray"); + } + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + _designedWidget = designedWidget; + this.SuspendLayout (); + this.DesignerPanel.Widgets.Add (designedWidget); + this.ResumeLayout (); + + this.ComponentTray = tray; + } + +#region Windows Forms Designer generated code + /// <summary> + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// </summary> + private void InitializeComponent() { + this.ComponentTrayPanel = new ShiftUI.Panel(); + this.splitter1 = new ShiftUI.Splitter(); + this.DesignerPanel = new ShiftUI.Panel(); + this.SuspendLayout(); + // + // ComponentTrayPanel + // + this.ComponentTrayPanel.BackColor = System.Drawing.Color.LemonChiffon; + this.ComponentTrayPanel.Dock = ShiftUI.DockStyle.Bottom; + this.ComponentTrayPanel.Location = new System.Drawing.Point(0, 194); + this.ComponentTrayPanel.Name = "ComponentTrayPanel"; + this.ComponentTrayPanel.Size = new System.Drawing.Size(292, 72); + this.ComponentTrayPanel.TabIndex = 1; + this.ComponentTrayPanel.Visible = false; + // + // splitter1 + // + this.splitter1.Dock = ShiftUI.DockStyle.Bottom; + this.splitter1.Location = new System.Drawing.Point(0, 186); + this.splitter1.Name = "splitter1"; + this.splitter1.Size = new System.Drawing.Size(292, 8); + this.splitter1.TabIndex = 2; + this.splitter1.TabStop = false; + this.splitter1.Visible = false; + // + // DesignerPanel + // + this.DesignerPanel.AutoScroll = true; + this.DesignerPanel.BackColor = System.Drawing.Color.White; + this.DesignerPanel.Dock = ShiftUI.DockStyle.Fill; + this.DesignerPanel.Location = new System.Drawing.Point(0, 0); + this.DesignerPanel.Name = "DesignerPanel"; + this.DesignerPanel.Size = new System.Drawing.Size(292, 266); + this.DesignerPanel.TabIndex = 0; + this.DesignerPanel.MouseUp += new ShiftUI.MouseEventHandler(this.DesignerPanel_MouseUp); + this.DesignerPanel.MouseMove += new ShiftUI.MouseEventHandler(this.DesignerPanel_MouseMove); + this.DesignerPanel.MouseDown += new ShiftUI.MouseEventHandler(this.DesignerPanel_MouseDown); + this.DesignerPanel.Paint += new PaintEventHandler (DesignerPanel_Paint); + // + // DesignerViewFrame + // + this.Widgets.Add(this.splitter1); + this.Widgets.Add(this.ComponentTrayPanel); + this.Widgets.Add(this.DesignerPanel); + this.Name = "UserWidget1"; + this.Size = new System.Drawing.Size(292, 266); + this.Dock = DockStyle.Fill; + this.ResumeLayout(false); + } + +#endregion + + private bool _mouseDown = false; + private bool _firstMove = false; + + void DesignerPanel_Paint (object sender, PaintEventArgs e) + { + IUISelectionService selectionServ = this.DesignedWidget.Site.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null) + selectionServ.PaintAdornments (this.DesignerPanel, e.Graphics); + } + + void DesignerPanel_MouseDown(object sender, ShiftUI.MouseEventArgs e) + { + _mouseDown = true; + _firstMove = true; + } + + void DesignerPanel_MouseMove(object sender, ShiftUI.MouseEventArgs e) + { + IUISelectionService selectionServ = this.DesignedWidget.Site.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ == null) + return; + + selectionServ.SetCursor (e.X, e.Y); + if (_mouseDown) { + if (_firstMove) { + selectionServ.MouseDragBegin (this.DesignerPanel, e.X, e.Y); + _firstMove = false; + } + else { + selectionServ.MouseDragMove (e.X, e.Y); + } + } + else if (selectionServ.SelectionInProgress) { + selectionServ.MouseDragMove (e.X, e.Y); + } + } + + void DesignerPanel_MouseUp(object sender, ShiftUI.MouseEventArgs e) + { + IUISelectionService selectionServ = this.DesignedWidget.Site.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (_mouseDown) { + if (selectionServ != null) + selectionServ.MouseDragEnd (false); + _mouseDown = false; + } + else if (selectionServ.SelectionInProgress) { + selectionServ.MouseDragEnd (false); + } + } + + // by default the component tray is hidden and essentially should be shown once there + // is a component added to it + // + public void ShowComponentTray () + { + if (!this.ComponentTray.Visible) { + this.ComponentTrayPanel.Visible = true; + this.ComponentTray.Visible = true; + this.splitter1.Visible = true; + } + } + + public void HideComponentTray () + { + if (!this.ComponentTray.Visible) { + this.ComponentTrayPanel.Visible = true; + this.ComponentTray.Visible = true; + this.splitter1.Visible = true; + } + } + + public ComponentTray ComponentTray { + get { return _componentTray; } + set { + this.SuspendLayout (); + this.ComponentTrayPanel.Widgets.Remove (_componentTray); + this.ComponentTrayPanel.Widgets.Add (value); + this.ResumeLayout (); + _componentTray = value; + _componentTray.Visible = false; + } + } + + public Widget DesignedWidget { + get { return _designedWidget; } + set { + } + } + + protected override void Dispose (bool disposing) + { + if (_designedWidget != null) { + this.DesignerPanel.Widgets.Remove (_designedWidget); + _designedWidget = null; + } + + if (_componentTray != null) { + this.ComponentTrayPanel.Widgets.Remove (_componentTray); + _componentTray.Dispose (); + _componentTray = null; + } + + base.Dispose (disposing); + } + } +#endregion + + + + + private DesignerViewFrame _designerViewFrame; + + public DocumentDesigner () + { + } + + private DesignerViewFrame View { + get { return _designerViewFrame; } + } + +#region Initialization + public override void Initialize (IComponent component) + { + base.Initialize (component); + + _designerViewFrame = new DesignerViewFrame (this.Widget, new ComponentTray (this, component.Site)); + _designerViewFrame.DesignedWidget.Location = new Point (15, 15); + SetValue (this.Component, "Location", new Point (0, 0)); + + IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + if (componentChangeSvc != null) { + componentChangeSvc.ComponentAdded += new ComponentEventHandler (OnComponentAdded); + componentChangeSvc.ComponentRemoved += new ComponentEventHandler (OnComponentRemoved); + } + + IMenuCommandService menuCommands = GetService (typeof (IMenuCommandService)) as IMenuCommandService; + IServiceContainer serviceContainer = this.GetService (typeof (IServiceContainer)) as IServiceContainer; + if (menuCommands != null && serviceContainer != null) + new DefaultMenuCommands (serviceContainer).AddTo (menuCommands); + InitializeSelectionService (); + } + + private void InitializeSelectionService () + { + IUISelectionService guiSelectionService = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (guiSelectionService == null) { + IServiceContainer serviceContainer = this.GetService (typeof (IServiceContainer)) as IServiceContainer; + serviceContainer.AddService (typeof (IUISelectionService), (IUISelectionService) new UISelectionService (serviceContainer)); + } + + ISelectionService selectionService = this.GetService (typeof (ISelectionService)) as ISelectionService; + selectionService.SetSelectedComponents (new IComponent[] { this.Component }); + } + + + protected override void Dispose (bool disposing) + { + if (disposing) { + if (_designerViewFrame != null) { + _designerViewFrame.Dispose (); + _designerViewFrame = null; + + } + IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + if (componentChangeSvc != null) { + componentChangeSvc.ComponentAdded -= new ComponentEventHandler (OnComponentAdded); + componentChangeSvc.ComponentRemoved -= new ComponentEventHandler (OnComponentRemoved); + } + } + base.Dispose (disposing); + } +#endregion + + +#region MSDN says overriden + + public override GlyphCollection GetGlyphs (GlyphSelectionType selectionType) + { + return base.GetGlyphs (selectionType); + } + + protected override void WndProc (ref Message m) + { + base.WndProc (ref m); + } + + protected override void OnCreateHandle () + { + base.OnCreateHandle (); + } + +#endregion + + +#region Components and ComponentTray + + private void OnComponentAdded (object sender, ComponentEventArgs args) + { + if (!(args.Component is Widget)) { + this.View.ComponentTray.AddComponent (args.Component); + if (this.View.ComponentTray.ComponentCount > 0) { + if (!this.View.ComponentTray.Visible) + this.View.ShowComponentTray (); + } + } + } + + private void OnComponentRemoved (object sender, ComponentEventArgs args) + { + if (!(args.Component is Widget)) { + this.View.ComponentTray.RemoveComponent (args.Component); + if (this.View.ComponentTray.ComponentCount == 0) { + if (this.View.ComponentTray.Visible) + this.View.HideComponentTray (); + } + } + } +#endregion + + +#region IRootDesigner + + object IRootDesigner.GetView (ViewTechnology technology) + { + if (technology != ViewTechnology.Default) + throw new ArgumentException ("Only ViewTechnology.WindowsForms is supported."); + return _designerViewFrame; + } + + ViewTechnology[] IRootDesigner.SupportedTechnologies { + get { + return new ViewTechnology[] { ViewTechnology.Default }; + } + } +#endregion + + +#region IToolBoxUser + + // Indicates whether the specified tool is supported by the designer. + // If it is not the tool is disabled in the toolbox. + // + // Used for subclasses, e.g the FormDocumentDesigner won't accept a Form? + // + bool IToolboxUser.GetToolSupported (ToolboxItem tool) + { + return this.GetToolSupported (tool); + } + + protected virtual bool GetToolSupported (ToolboxItem tool) + { + return true; + } + + + // Handles the behavior that occurs when a user double-clicks a toolbox item. + // + void IToolboxUser.ToolPicked (ToolboxItem tool) + { + this.ToolPicked (tool); + } + + // ToolPicked is called when the user double-clicks on a toolbox item. + // The document designer should create a component for the specified tool. + // Only tools that are enabled in the toolbox will be passed to this method. + // + // I create the component in the parent container of the primary selection. + // If not available I create it in the rootcomponent (this essentially :-) ) + // + protected virtual void ToolPicked (ToolboxItem tool) + { + ISelectionService selectionSvc = GetService (typeof (ISelectionService)) as ISelectionService; + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + if (selectionSvc != null && host != null) { + IDesigner designer = host.GetDesigner ((IComponent) selectionSvc.PrimarySelection); + if (designer is ParentWidgetDesigner) + ParentWidgetDesigner.InvokeCreateTool ((ParentWidgetDesigner) designer, tool); + else + this.CreateTool (tool); + } + else { + this.CreateTool (tool); + } + IToolboxService tbServ = this.GetService (typeof (IToolboxService)) as IToolboxService; + tbServ.SelectedToolboxItemUsed (); + } +#endregion + + +#region Properties + // A root designer can be resized to the bottom and to the right. + // + public override SelectionRules SelectionRules { + get { + return (SelectionRules.RightSizeable | SelectionRules.BottomSizeable | SelectionRules.Visible); + } + } +#endregion + + +#region Metadata filtering and Design-Time properties + + // MSDN says that this adds the "BackColor" and "Location" browsable design-time propeties. + // + // The reason for overwriting the Location property created by the ControDesigner is that + // the root component is not draggable (e.g a form has a static location in the DesignerViewFrame) + // + protected override void PreFilterProperties (IDictionary properties) + { + base.PreFilterProperties (properties); + + PropertyDescriptor propertyDescriptor = properties["BackColor"] as PropertyDescriptor; + if (propertyDescriptor != null) { + properties["BackColor"] = TypeDescriptor.CreateProperty (typeof (DocumentDesigner), + propertyDescriptor, + new Attribute[] { new DefaultValueAttribute (System.Drawing.SystemColors.Control) }); + } + + propertyDescriptor = properties["Location"] as PropertyDescriptor; + if (propertyDescriptor != null) { + properties["Location"] = TypeDescriptor.CreateProperty (typeof (DocumentDesigner), + propertyDescriptor, + new Attribute[] { new DefaultValueAttribute (typeof (Point), "0, 0") }); + } + } + + private Color BackColor { + get { return (Color) ShadowProperties["BackColor"]; } + set { + ShadowProperties["BackColor"] = value; + this.Widget.BackColor = value; + } + } + + private Point Location { + get { return (Point) ShadowProperties["Location"]; } + set { ShadowProperties["Location"] = value; } + } +#endregion + + } +} diff --git a/source/ShiftUI/Design/EventsTab.cs b/source/ShiftUI/Design/EventsTab.cs new file mode 100644 index 0000000..570f850 --- /dev/null +++ b/source/ShiftUI/Design/EventsTab.cs @@ -0,0 +1,101 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004-2008 Novell, Inc. +// +// Authors: +// Dennis Hayes ([email protected]) +// Rafael Teixeira ([email protected]) +// Ivan N. Zlatev ([email protected]) +// + +// COMPLETE + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; + +namespace ShiftUI.Design +{ + public class EventsTab : PropertyTab + { + private EventsTab() + { + } + + private IServiceProvider serviceProvider; + + public EventsTab(IServiceProvider sp) + { + this.serviceProvider = sp; + } + + public override string HelpKeyword { + get { return TabName; } + } + + public override string TabName { + get { return "Events"; } + } + + public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object component, + Attribute[] attributes) + { + IEventBindingService eventPropertySvc = null; + EventDescriptorCollection events = null; + + if (serviceProvider != null) + eventPropertySvc = (IEventBindingService) serviceProvider.GetService(typeof(IEventBindingService)); + + if (eventPropertySvc == null) + return new PropertyDescriptorCollection(null); + + if (attributes != null) + events = TypeDescriptor.GetEvents(component, attributes); + else + events = TypeDescriptor.GetEvents(component); + + // Return event properties for the event descriptors. + return eventPropertySvc.GetEventProperties(events); + } + + public override PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes) + { + return this.GetProperties(null, component, attributes); + } + + public override bool CanExtend(object extendee) + { + return false; + } + + public override PropertyDescriptor GetDefaultProperty(object obj) + { + if (serviceProvider == null) + return null; + + EventDescriptor defaultEvent = TypeDescriptor.GetDefaultEvent (obj); + IEventBindingService eventPropertySvc = (IEventBindingService) serviceProvider.GetService(typeof(IEventBindingService)); + if (defaultEvent != null && eventPropertySvc != null) + return eventPropertySvc.GetEventProperty (defaultEvent); + return null; + } + + } +} diff --git a/source/ShiftUI/Design/FormDocumentDesigner.cs b/source/ShiftUI/Design/FormDocumentDesigner.cs new file mode 100644 index 0000000..d3f8b14 --- /dev/null +++ b/source/ShiftUI/Design/FormDocumentDesigner.cs @@ -0,0 +1,86 @@ +// +// ShiftUI.Design.FormDocumentDesigner +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2008 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; + +namespace ShiftUI.Design +{ + internal class FormDocumentDesigner : DocumentDesigner + { + + public FormDocumentDesigner () + { + } + + public override void Initialize (IComponent component) + { + Form form = component as Form; + if (form == null) + throw new NotSupportedException ("FormDocumentDesigner can be initialized only with Forms"); + + form.TopLevel = false; + form.Visible = true; + base.Initialize (component); + } + + public override bool CanParent (Widget control) + { + if (control is Form) + return false; + return base.CanParent (control); + } + + protected override void WndProc (ref Message m) + { + // Filter out titlebar clicks + // + switch ((Native.Msg) m.Msg) { + case Native.Msg.WM_NCLBUTTONDBLCLK: + case Native.Msg.WM_NCLBUTTONDOWN: + case Native.Msg.WM_NCMBUTTONDBLCLK: + case Native.Msg.WM_NCMBUTTONDOWN: + case Native.Msg.WM_NCRBUTTONDBLCLK: + case Native.Msg.WM_NCRBUTTONDOWN: + ISelectionService selectionServ = this.GetService (typeof (ISelectionService)) as ISelectionService; + if (selectionServ != null) + selectionServ.SetSelectedComponents (new object[] { this.Component }); + break; + default: + base.WndProc (ref m); + break; + } + } + } +} diff --git a/source/ShiftUI/Design/IMenuEditorService.cs b/source/ShiftUI/Design/IMenuEditorService.cs new file mode 100644 index 0000000..2d90849 --- /dev/null +++ b/source/ShiftUI/Design/IMenuEditorService.cs @@ -0,0 +1,34 @@ + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; + +namespace ShiftUI.Design +{ + public interface IMenuEditorService + { + Menu GetMenu(); + bool IsActive(); + bool MessageFilter(ref Message m); + void SetMenu(Menu menu); + void SetSelection(MenuItem item); + } +} diff --git a/source/ShiftUI/Design/IMessageReceiver.cs b/source/ShiftUI/Design/IMessageReceiver.cs new file mode 100644 index 0000000..b36ad31 --- /dev/null +++ b/source/ShiftUI/Design/IMessageReceiver.cs @@ -0,0 +1,39 @@ +// +// ShiftUI.Design.IMessageReceiver +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using ShiftUI; + +namespace ShiftUI.Design +{ + internal interface IMessageReceiver + { + void WndProc (ref Message m); + } +} diff --git a/source/ShiftUI/Design/IUISelectionService.cs b/source/ShiftUI/Design/IUISelectionService.cs new file mode 100644 index 0000000..7c8ad47 --- /dev/null +++ b/source/ShiftUI/Design/IUISelectionService.cs @@ -0,0 +1,71 @@ +// +// ShiftUI.Design.IUISelectionService +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Drawing.Drawing2D; +using ShiftUI; + +namespace ShiftUI.Design +{ + + + internal interface IUISelectionService + { + bool SelectionInProgress { + get; + } + bool DragDropInProgress { + get; + } + bool ResizeInProgress { + get; + } + + Rectangle SelectionBounds { + get; + } + + void MouseDragBegin (Widget container, int x, int y); + void MouseDragMove (int x, int y); + void MouseDragEnd (bool cancel); + + void DragBegin (); + void DragOver (Widget container, int x, int y); + void DragDrop (bool cancel, Widget container, int x, int y); + + void PaintAdornments (Widget container, Graphics gfx); + bool SetCursor (int x, int y); + + bool AdornmentsHitTest (Widget control, int x, int y); + } +} diff --git a/source/ShiftUI/Design/IUIService.cs b/source/ShiftUI/Design/IUIService.cs new file mode 100644 index 0000000..71368dd --- /dev/null +++ b/source/ShiftUI/Design/IUIService.cs @@ -0,0 +1,52 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004 Novell, Inc. +// +// Authors: +// Andreas Nahr ([email protected]) +// + +// NOT COMPLETE + +using System.Runtime.InteropServices; +using System.Collections; +using System; + +namespace ShiftUI.Design +{ + [Guid ("06a9c74b-5e32-4561-be73-381b37869f4f")] + public interface IUIService + { + IDictionary Styles {get;} + + bool CanShowComponentEditor (object component); + IWin32Window GetDialogOwnerWindow (); + void SetUIDirty (); + bool ShowComponentEditor (object component, IWin32Window parent); + void ShowError (Exception ex); + void ShowError (string message); + void ShowError (Exception ex, string message); + DialogResult ShowDialog (Form form); + void ShowMessage (string message); + void ShowMessage (string message, string caption); + DialogResult ShowMessage (string message, string caption, MessageBoxButtons buttons); + bool ShowToolWindow (Guid toolWindow); + } +} diff --git a/source/ShiftUI/Design/IWindowsFormsEditorService.cs b/source/ShiftUI/Design/IWindowsFormsEditorService.cs new file mode 100644 index 0000000..cfd5601 --- /dev/null +++ b/source/ShiftUI/Design/IWindowsFormsEditorService.cs @@ -0,0 +1,35 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004 Novell, Inc. +// +// Authors: +// Andreas Nahr ([email protected]) +// + +// NOT COMPLETE + +namespace ShiftUI.Design +{ + public interface IWindowsFormsEditorService { + void CloseDropDown (); + void DropDownWidget (Widget Widget); + DialogResult ShowDialog (Form dialog); + } +} diff --git a/source/ShiftUI/Design/Native.cs b/source/ShiftUI/Design/Native.cs new file mode 100644 index 0000000..bd86c42 --- /dev/null +++ b/source/ShiftUI/Design/Native.cs @@ -0,0 +1,216 @@ +// +// ShiftUI.Design.Native +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Drawing; +using ShiftUI; +using System.Runtime.InteropServices; +using System.Reflection; + + +namespace ShiftUI +{ + + internal class Native + { + + private static Type _xplatuiType; + + static Native () + { + Assembly assembly = Assembly.GetExecutingAssembly(); + if (assembly == null) + throw new InvalidOperationException ("Can't load ShiftUI assembly."); + + _xplatuiType = assembly.GetType ("ShiftUI.XplatUI"); + if (_xplatuiType == null) + throw new InvalidOperationException ("Can't find the ShiftUI.XplatUI type."); + } + + private static object InvokeMethod (string methodName, object[] args) + { + return InvokeMethod (methodName, args, null); + } + + // will also match types + private static object InvokeMethod (string methodName, object[] args, Type[] types) + { + MethodInfo method = null; + + if (types != null) { + method = _xplatuiType.GetMethod (methodName, BindingFlags.NonPublic | BindingFlags.Static | + BindingFlags.InvokeMethod, null, types, null); + } else { + method = _xplatuiType.GetMethod (methodName, BindingFlags.NonPublic | BindingFlags.Static | + BindingFlags.InvokeMethod); + } + + if (method == null) + throw new InvalidOperationException (methodName + " not found!"); + + return method.Invoke (null, args); + } + + public static void DefWndProc (ref Message m) + { + object[] args = new object[] { m }; + m.Result = (IntPtr) InvokeMethod ("DefWndProc", args); + m = (Message) args[0]; + } + + public static IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam) + { + + Assembly assembly = Assembly.GetExecutingAssembly(); + Type refType = assembly.GetType ("ShiftUI.Message&"); + object[] args = new object[] { Message.Create (hwnd, (int)message, wParam, lParam) }; + InvokeMethod ("SendMessage", args, new Type[] { refType }); + return ((Message)args[0]).Result; + } + + public static Point PointToClient (Widget control, Point point) + { + if (control == null) + throw new ArgumentNullException ("control"); + + object[] args = new object[] { control.Handle, point.X, point.Y }; + InvokeMethod ("ScreenToClient", args); + return new Point ((int) args[1], (int) args[2]); + } + + public static IntPtr SetParent (IntPtr childHandle, IntPtr parentHandle) + { + return (IntPtr) InvokeMethod ("SetParent", new object[] { childHandle, parentHandle }); + } + + +#region Helpers + public static int HiWord (int dword) + { + // 12345678 -> 12340000 -> 00001234 + return ((dword >> 16) & 0x0000ffff); + } + + public static int LoWord (int dword) + { + // 12345678 -> 00005678 + return (dword & 0x0000ffff); + } + + public static IntPtr LParam (int hiword, int loword) + { + // results [hiword|loword] dword + // + return (IntPtr)((loword << 16) | (hiword & 0x0000FFFF)); + } +#endregion + + public enum Msg { + WM_CREATE = 0x0001, + WM_SETFOCUS = 0x0007, + WM_PAINT = 0X000F, + WM_CANCELMODE = 0x001F, + WM_SETCURSOR = 0x0020, + WM_CONTEXTMENU = 0x007B, + WM_NCHITTEST = 0x0084, + // + // AccessabilityObject + // + WM_GETOBJECT = 0x003D, + // + // Mouse input - Client area + // + WM_MOUSEFIRST = 0x0200, + WM_MOUSEMOVE = 0x0200, + WM_LBUTTONDOWN = 0x0201, + WM_LBUTTONUP = 0x0202, + WM_LBUTTONDBLCLK = 0x0203, + WM_RBUTTONDOWN = 0x0204, + WM_RBUTTONUP = 0x0205, + WM_RBUTTONDBLCLK = 0x0206, + WM_MBUTTONDOWN = 0x0207, + WM_MBUTTONUP = 0x0208, + WM_MBUTTONDBLCLK = 0x0209, + WM_MOUSEWHEEL = 0x020A, + WM_MOUSELAST = 0x020A, + WM_NCMOUSEHOVER = 0x02A0, + WM_MOUSEHOVER = 0x02A1, + WM_NCMOUSELEAVE = 0x02A2, + WM_MOUSELEAVE = 0x02A3, + // + // Mouse input - Non-client area + // + WM_NCMOUSEMOVE = 0x00A0, + WM_NCLBUTTONDOWN = 0x00A1, + WM_NCLBUTTONUP = 0x00A2, + WM_NCLBUTTONDBLCLK = 0x00A3, + WM_NCRBUTTONDOWN = 0x00A4, + WM_NCRBUTTONUP = 0x00A5, + WM_NCRBUTTONDBLCLK = 0x00A6, + WM_NCMBUTTONDOWN = 0x00A7, + WM_NCMBUTTONUP = 0x00A8, + WM_NCMBUTTONDBLCLK = 0x00A9, + // + // Keyboard input + // + WM_KEYFIRST = 0x0100, + WM_KEYDOWN = 0x0100, + WM_KEYUP = 0x0101, + WM_CHAR = 0x0102, + WM_DEADCHAR = 0x0103, + WM_SYSKEYDOWN = 0x0104, + WM_SYSKEYUP = 0x0105, + WM_SYS1CHAR = 0x0106, + WM_SYSDEADCHAR = 0x0107, + WM_KEYLAST = 0x0108, + // + // Scrolling + // + WM_HSCROLL = 0x0114, + WM_VSCROLL = 0x0115, + + // + // IME - International Text + // + WM_IME_SETCONTEXT = 0x0281, + WM_IME_NOTIFY = 0x0282, + WM_IME_CONTROL = 0x0283, + WM_IME_COMPOSITIONFULL = 0x0284, + WM_IME_SELECT = 0x0285, + WM_IME_CHAR = 0x0286, + WM_IME_REQUEST = 0x0288, + WM_IME_KEYDOWN = 0x0290, + WM_IME_KEYUP = 0x0291, + + // MWF Custom msgs + // + WM_MOUSE_ENTER = 0x0401, + } + } +} + diff --git a/source/ShiftUI/Design/ParentControlDesigner.cs b/source/ShiftUI/Design/ParentControlDesigner.cs new file mode 100644 index 0000000..0e906e7 --- /dev/null +++ b/source/ShiftUI/Design/ParentControlDesigner.cs @@ -0,0 +1,726 @@ +// +// ShiftUI.Design.ParentWidgetDesigner +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using ShiftUI; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Design; +using System.Collections; +using ShiftUI.Design.Behavior; + +namespace ShiftUI.Design + +{ + + public class ParentWidgetDesigner : WidgetDesigner + { + + public ParentWidgetDesigner () + { + } + + +#region Initialization + // Settings paths taken from the example at: + // http://msdn2.microsoft.com/en-us/library/system.componentmodel.design.idesigneroptionservice.aspx + // + public override void Initialize (IComponent component) + { + base.Initialize (component); + + this.Widget.AllowDrop = true; + + // Initialize the default values of the Design-Time properties. + // + _defaultDrawGrid = true; + _defaultSnapToGrid = true; + _defaultGridSize = new Size (8, 8); + + // If the parent Widget of the designed one has a ParentDesigner then inherit the values + // from it's designer. + // + if (this.Widget.Parent != null) { + ParentWidgetDesigner parentDesigner = GetParentWidgetDesignerOf (Widget.Parent); + if (parentDesigner != null) { + _defaultDrawGrid = (bool) GetValue (parentDesigner.Component, "DrawGrid"); + _defaultSnapToGrid = (bool) GetValue (parentDesigner.Component, "SnapToGrid"); + _defaultGridSize = (Size) GetValue (parentDesigner.Component, "GridSize"); + } + } + else { + // Else retrieve them through the IDesignerOptionService (if available) + // + IDesignerOptionService options = GetService (typeof (IDesignerOptionService)) as + IDesignerOptionService; + if (options != null) { + object value = null; + value = options.GetOptionValue (@"WindowsFormsDesigner\General", "DrawGrid"); + if (value is bool) + _defaultDrawGrid = (bool) value; + + value = options.GetOptionValue (@"WindowsFormsDesigner\General", "SnapToGrid"); + if (value is bool) + _defaultSnapToGrid = (bool) value; + + value = options.GetOptionValue (@"WindowsFormsDesigner\General", "GridSize"); + if (value is Size) + _defaultGridSize = (Size) value; + } + } + + IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + if (componentChangeSvc != null) { + componentChangeSvc.ComponentRemoving += new ComponentEventHandler (OnComponentRemoving); + componentChangeSvc.ComponentRemoved += new ComponentEventHandler (OnComponentRemoved); + } + + // At the end set whatever we've managed to get + // + _drawGrid = _defaultDrawGrid; + _snapToGrid = _defaultSnapToGrid; + _gridSize = _defaultGridSize; + } + + protected override void Dispose (bool disposing) + { + if (disposing) { + EnableDragDrop (false); + OnMouseDragEnd (true); + } + base.Dispose (disposing); + } +#endregion + + +#region IToolboxService Related + + // This is the code that is executed when you drop a tool from the Toolbox in the designer. + // + + protected static void InvokeCreateTool (ParentWidgetDesigner toInvoke, ToolboxItem tool) + { + if (toInvoke != null) + toInvoke.CreateTool (tool); + } + + protected void CreateTool (ToolboxItem tool) + { + CreateToolCore (tool, DefaultWidgetLocation.X, DefaultWidgetLocation.Y, 0, 0, true, false); + } + + protected void CreateTool (ToolboxItem tool, Point location) + { + CreateToolCore (tool, location.X, location.Y, 0, 0, true, false); + } + + protected void CreateTool (ToolboxItem tool, Rectangle bounds) + { + CreateToolCore (tool, bounds.X, bounds.Y, bounds.Width, bounds.Width, true, true); + } + + // Creates a component from a ToolboxItem, sets its location and size if available and snaps it's + // location to the grid. + // + protected virtual IComponent[] CreateToolCore (ToolboxItem tool, int x, int y, int width, int height, + bool hasLocation, bool hasSize) + { + if (tool == null) + throw new ArgumentNullException ("tool"); + + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + DesignerTransaction transaction = host.CreateTransaction ("Create components in tool '" + tool.DisplayName + "'"); + IComponent[] components = tool.CreateComponents (host); + + foreach (IComponent component in components) + { + WidgetDesigner controlDesigner = host.GetDesigner (component) as WidgetDesigner; + if (controlDesigner == null) { // not a Widget, but e.g. a plain Component + continue; + } else if (!this.CanParent (controlDesigner)) { + host.DestroyComponent (component); + continue; + } + + Widget control = component as Widget; + if (control != null) { + this.Widget.SuspendLayout (); + // set parent instead of controls.Add so that it gets serialized for Undo/Redo + TypeDescriptor.GetProperties (control)["Parent"].SetValue (control, this.Widget); + this.Widget.SuspendLayout (); + + if (hasLocation) + base.SetValue (component, "Location", this.SnapPointToGrid (new Point (x, y))); + else + base.SetValue (component, "Location", this.SnapPointToGrid (this.DefaultWidgetLocation)); + + if (hasSize) + base.SetValue (component, "Size", new Size (width, height)); + + this.Widget.Refresh (); + } + } + ISelectionService selectionServ = this.GetService (typeof (ISelectionService)) as ISelectionService; + if (selectionServ != null) + selectionServ.SetSelectedComponents (components, SelectionTypes.Replace); + transaction.Commit (); + return components; + } + +#endregion + + +#region Drag and Drop + + // If the control is not already parented return true + // + public virtual bool CanParent (Widget control) + { + if (control != null) + return !control.Contains (this.Widget); + + return false; + } + + public virtual bool CanParent (WidgetDesigner designer) + { + return CanParent (designer.Widget); + } + + protected override void OnDragDrop (DragEventArgs e) + { + IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null) { + // once this is fired the parent control (parentcontroldesigner) will start getting dragover events. + // + Point location = this.SnapPointToGrid (this.Widget.PointToClient (new Point (e.X, e.Y))); + selectionServ.DragDrop (false, this.Widget, location.X, location.Y); + } + } + + protected override void OnDragEnter (DragEventArgs e) + { + this.Widget.Refresh (); + } + + protected override void OnDragLeave (EventArgs e) + { + this.Widget.Refresh (); + } + + protected override void OnDragOver (DragEventArgs e) + { + IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null) { + // once WidgetDesigner.MouseDragBegin is called this will start getting dragover events. + // + Point location = this.SnapPointToGrid (this.Widget.PointToClient (new Point (e.X, e.Y))); + selectionServ.DragOver (this.Widget, location.X, location.Y); + } + e.Effect = DragDropEffects.Move; + } +#endregion + + +#region Properties + // The default location where a control is placed, when added to the designer + // + protected virtual Point DefaultWidgetLocation { + get { return new Point (0, 0); } + } + + + protected override bool EnableDragRect { + get { return true; } + } +#endregion + +#region ComponentChange + + private void OnComponentRemoving (object sender, ComponentEventArgs args) + { + IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + Widget control = args.Component as Widget; + if (control != null && control.Parent == this.Widget && componentChangeSvc != null) + componentChangeSvc.OnComponentChanging (args.Component, TypeDescriptor.GetProperties (args.Component)["Parent"]); + } + + private void OnComponentRemoved (object sender, ComponentEventArgs args) + { + IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService; + Widget control = args.Component as Widget; + if (control != null && control.Parent == this.Widget && componentChangeSvc != null) { + control.Parent = null; + componentChangeSvc.OnComponentChanged (args.Component, + TypeDescriptor.GetProperties (args.Component)["Parent"], + this.Widget, null); + } + } +#endregion + +#region Design-Time Properties + + private bool _defaultDrawGrid; + private bool _defaultSnapToGrid; + private Size _defaultGridSize; + private bool _drawGrid; + private bool _snapToGrid; + private Size _gridSize; + + //This method adds the following design-time browsable properties: + // "DrawGrid", "SnapToGrid", and "GridSize". + // + protected override void PreFilterProperties (IDictionary properties) + { + base.PreFilterProperties (properties); + + properties["DrawGrid"] = TypeDescriptor.CreateProperty (typeof (ParentWidgetDesigner), + "DrawGrid", + typeof (bool), + new Attribute[] { + BrowsableAttribute.Yes, + DesignOnlyAttribute.Yes, + new DescriptionAttribute ( + "Indicates whether or not to draw the positioning grid."), + CategoryAttribute.Design + }); + + properties["SnapToGrid"] = TypeDescriptor.CreateProperty (typeof (ParentWidgetDesigner), + "SnapToGrid", + typeof (bool), + new Attribute[] { + BrowsableAttribute.Yes, + DesignOnlyAttribute.Yes, + new DescriptionAttribute ( + "Determines if controls should snap to the positioning grid."), + CategoryAttribute.Design + }); + + properties["GridSize"] = TypeDescriptor.CreateProperty (typeof (ParentWidgetDesigner), + "GridSize", + typeof (Size), + new Attribute[] { + BrowsableAttribute.Yes, + DesignOnlyAttribute.Yes, + new DescriptionAttribute ( + "Determines the size of the positioning grid."), + CategoryAttribute.Design + }); + + } + + + // Informs all children controls' ParentWidgetDesigners that the grid properties + // have changed and passes them + // + private void PopulateGridProperties () + { + // Widget.Invalidate (true) will redraw the control and it's children + // this will cause a WM_PAINT message to be send and the WidgetDesigenr will raise + // the OnPaintAdornments, where the grid drawing takes place. + // + // Note that this should be called *after* the grid properties have changed :-) + // + this.Widget.Invalidate (false); + + if (this.Widget != null) { + ParentWidgetDesigner designer = null; + foreach (Widget control in this.Widget.Widgets) { + designer = this.GetParentWidgetDesignerOf (control); + if (designer != null) + designer.OnParentGridPropertiesChanged (this); + } + } + } + + // Called by the parent ParentWidgetDesigner when it is populating the grid-related + // design-time properties changes + // + private void OnParentGridPropertiesChanged (ParentWidgetDesigner parentDesigner) + { + SetValue (this.Component, "DrawGrid", (bool) GetValue (parentDesigner.Component, "DrawGrid")); + SetValue (this.Component, "SnapToGrid", (bool) GetValue (parentDesigner.Component, "SnapToGrid")); + SetValue (this.Component, "GridSize", (Size) GetValue (parentDesigner.Component, "GridSize")); + + // Set also the default values to be those, because we should + // match the parent ParentWidgetDesigner values. + // called recursivly, so I will rather go for slower, but no stack-overflowable code + // + _defaultDrawGrid = (bool) GetValue (parentDesigner.Component, "DrawGrid"); + _defaultSnapToGrid = (bool) GetValue (parentDesigner.Component, "SnapToGrid"); + _defaultGridSize = (Size) GetValue (parentDesigner.Component, "GridSize"); + + this.PopulateGridProperties (); + } + + + // Retrieves the ParentWidgetDesigner of the specified control if available, + // else returns null. + // + private ParentWidgetDesigner GetParentWidgetDesignerOf (Widget control) + { + if (control != null) { + IDesignerHost designerHost = GetService (typeof (IDesignerHost)) as IDesignerHost; + if (designerHost != null) { + ParentWidgetDesigner designer = null; + designer = designerHost.GetDesigner (this.Widget.Parent) as ParentWidgetDesigner; + if (designer != null) + return designer; + } + } + return null; + } + + protected virtual bool DrawGrid { + get { return _drawGrid; } + set { + _drawGrid = value; + + if (value == false) + SetValue (this.Component, "SnapToGrid", false); + + PopulateGridProperties (); + } + } + + private bool SnapToGrid { + get { return _snapToGrid; } + set { + _snapToGrid = value; + PopulateGridProperties (); + } + } + + protected Size GridSize { + get { return _gridSize; } + set { + _gridSize = value; + PopulateGridProperties (); + } + } + + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconshouldpersistresetmethods.asp + // + // The ShouldSerializerPROPERTYNAME determines whether a property has changed from + // the default value and should get serialized. + // + // The ResetPROPERTYNAME resets the property to it's default value (used when + // one right clicks on a property in the property grid and clicks on "Reset". + // + + private bool ShouldSerializeDrawGrid () + { + return DrawGrid != _defaultDrawGrid; + } + + private void ResetDrawGrid () + { + this.DrawGrid = _defaultDrawGrid; + } + + private bool ShouldSerializeSnapToGrid () + { + return _drawGrid != _defaultDrawGrid; + } + + private void ResetSnapToGrid () + { + this.SnapToGrid = _defaultSnapToGrid; + } + + private bool ShouldSerializeGridSize () + { + return GridSize != _defaultGridSize; + } + + private void ResetGridSize () + { + this.GridSize = _defaultGridSize; + } +#endregion + + +#region Design-Time Mouse Drag and Drop + protected override void OnMouseDragBegin (int x, int y) + { + // do not call base here because the behaviour is specific for the WidgetDesgner (does IUISelectionService.DragBegin) + // + + IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null) { + // once WidgetDesigner.MouseDragBegin is fired this will start getting dragover events. + // + Point location = new Point (x, y); + IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost; + if (base.MouseButtonDown == MouseButtons.Middle && host != null && host.RootComponent != this.Widget) { + location = this.Widget.Parent.PointToClient (this.Widget.PointToScreen (new Point (x, y))); + // I have to do this, because I get DragOver events fired for the control I am actually dragging + // + this.Widget.AllowDrop = false; + selectionServ.DragBegin (); + } + else { + selectionServ.MouseDragBegin (this.Widget, location.X, location.Y); + } + } + } + + protected override void OnMouseDragMove (int x, int y) + { + IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null) { + Point location = new Point (x, y); + if (!selectionServ.SelectionInProgress) + location = this.SnapPointToGrid (new Point (x, y)); + + selectionServ.MouseDragMove (location.X, location.Y); + } + } + + protected override void OnMouseDragEnd (bool cancel) + { + IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selectionServ != null) { + // If there is a Toolbox component seleted then create it instead of finishing the selection + IToolboxService toolBoxService = this.GetService (typeof (IToolboxService)) as IToolboxService; + if (!cancel && toolBoxService != null && toolBoxService.GetSelectedToolboxItem () != null) { + if (selectionServ.SelectionInProgress) { + bool hasSize = selectionServ.SelectionBounds.Width > 0 && + selectionServ.SelectionBounds.Height > 0; + CreateToolCore (toolBoxService.GetSelectedToolboxItem (), + selectionServ.SelectionBounds.X, + selectionServ.SelectionBounds.Y, + selectionServ.SelectionBounds.Width, + selectionServ.SelectionBounds.Height, + true, hasSize); + toolBoxService.SelectedToolboxItemUsed (); + cancel = true; + } else if (!selectionServ.SelectionInProgress && + !selectionServ.ResizeInProgress && !selectionServ.DragDropInProgress){ + CreateTool (toolBoxService.GetSelectedToolboxItem (), _mouseDownPoint); + toolBoxService.SelectedToolboxItemUsed (); + cancel = true; + } + } + + if (selectionServ.SelectionInProgress || selectionServ.ResizeInProgress) + selectionServ.MouseDragEnd (cancel); + } + } + + protected override void OnDragComplete (DragEventArgs de) + { + base.OnDragComplete (de); + } + + Point _mouseDownPoint = Point.Empty; + + internal override void OnMouseDown (int x, int y) + { + _mouseDownPoint.X = x; + _mouseDownPoint.Y = y; + base.OnMouseDown (x, y); + } + + internal override void OnMouseUp () + { + base.OnMouseUp (); + if (!this.Widget.AllowDrop) // check MouseDragBegin for the reason of having this + this.Widget.AllowDrop = true; + _mouseDownPoint = Point.Empty; + } + + internal override void OnMouseMove (int x, int y) + { + IUISelectionService uiSelection = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (uiSelection != null) + uiSelection.SetCursor (x, y); + + base.OnMouseMove (x, y); + } + + // Align the point to the grid + // + private Point SnapPointToGrid (Point location) + { + Rectangle gridSurface = this.Widget.Bounds; + Size gridSize = (Size)GetValue (this.Component, "GridSize"); + + if ((bool)GetValue (this.Component, "SnapToGrid")) { + int x = location.X + (gridSize.Width - (location.X % gridSize.Width)); + if (x > gridSurface.Width) + x = gridSurface.Width - gridSize.Width; + + location.X = x; + + int y = location.Y + (gridSize.Height - (location.Y % gridSize.Height)); + if (y > gridSurface.Height) + y = gridSurface.Height - gridSize.Height; + + location.Y = y; + } + return location; + } + +#endregion + + + #region WndProc and Misc Message Handlers + + protected override void OnSetCursor () + { + if (this.Widget != null) { + IToolboxService tbService = GetService (typeof (IToolboxService)) as IToolboxService; + if (tbService != null) + tbService.SetCursor (); + else + base.OnSetCursor (); + } + } + + // Draws the design-time grid if DrawGrid == true + // + protected override void OnPaintAdornments (PaintEventArgs pe) + { + base.OnPaintAdornments (pe); + + bool drawGrid; + Size gridSize; + + // in case WM_PAINT is received before the IDesignerFilter is invoked to add + // those properties. + try { + drawGrid = (bool)GetValue (this.Component, "DrawGrid"); + } catch { + drawGrid = this.DrawGrid; + } + try { + gridSize = (Size)GetValue (this.Component, "GridSize"); + } catch { + gridSize = this.GridSize; + } + + if (drawGrid) { + GraphicsState state = pe.Graphics.Save (); + pe.Graphics.TranslateTransform (this.Widget.ClientRectangle.X, + this.Widget.ClientRectangle.Y); + WidgetPaint.DrawGrid (pe.Graphics, this.Widget.ClientRectangle, gridSize, this.Widget.BackColor); + pe.Graphics.Restore (state); + } + + IUISelectionService selection = this.GetService (typeof (IUISelectionService)) as IUISelectionService; + if (selection != null) + selection.PaintAdornments (this.Widget, pe.Graphics); + } + +#endregion + + + protected Widget GetWidget (object component) + { + IComponent comp = component as IComponent; + + if (comp != null && comp.Site != null) { + IDesignerHost host = comp.Site.GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host != null) { + WidgetDesigner designer = host.GetDesigner (comp) as WidgetDesigner; + if (designer != null) + return designer.Widget; + } + } + return null; + } + +#region NET_2_0 Stubs + [MonoTODO] + protected virtual bool AllowWidgetLasso { + get { return false; } + } + + [MonoTODO] + protected virtual bool AllowGenericDragBox { + get { return false; } + } + + [MonoTODO] + protected internal virtual bool AllowSetChildIndexOnDrop { + get { return false; } + } + + [MonoTODO] + public override IList SnapLines { + get { return new object [0]; } + } + + [MonoTODO] + protected ToolboxItem MouseDragTool { + get { return null; } + } + + [MonoTODO] + public override void InitializeNewComponent (IDictionary defaultValues) + { + base.InitializeNewComponent (defaultValues); + } + + [MonoTODO] + protected void AddPaddingSnapLines (ref ArrayList snapLines) + { + throw new NotImplementedException (); + } + + [MonoTODO] + protected virtual Widget GetParentForComponent (IComponent component) + { + throw new NotImplementedException (); + } + + [MonoTODO] + protected override WidgetBodyGlyph GetWidgetGlyph (GlyphSelectionType selectionType) + { + return base.GetWidgetGlyph (selectionType); + } + + [MonoTODO] + public override GlyphCollection GetGlyphs (GlyphSelectionType selectionType) + { + return base.GetGlyphs (selectionType); + } + + [MonoTODO] + protected Rectangle GetUpdatedRect (Rectangle originalRect, Rectangle dragRect, bool updateSize) + { + throw new NotImplementedException (); + } +#endregion + + } +} diff --git a/source/ShiftUI/Design/PropertyTab.cs b/source/ShiftUI/Design/PropertyTab.cs new file mode 100644 index 0000000..bb40e11 --- /dev/null +++ b/source/ShiftUI/Design/PropertyTab.cs @@ -0,0 +1,102 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004 Novell, Inc. +// +// Authors: Marek Safar ([email protected]) +// + +// COMPLETE + +using System.Drawing; +using System.ComponentModel; +using System; + +namespace ShiftUI.Design +{ + public abstract class PropertyTab: IExtenderProvider + { + Bitmap bitmap; + object[] components; + + protected PropertyTab () {} + + ~PropertyTab () + { + Dispose (false); + } + + public virtual Bitmap Bitmap { + get { + if (bitmap == null) { + Type t = base.GetType(); + bitmap = new Bitmap (t, t.Name + ".bmp"); + } + return bitmap; + } + } + + public virtual object[] Components { + get { return components; } + set { components = value; } + } + + public virtual string HelpKeyword { + get { return TabName; } + } + + public abstract string TabName { get; } + + public virtual bool CanExtend (object extendee) + { + return true; + } + + public virtual void Dispose() + { + Dispose (true); + GC.SuppressFinalize (this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && bitmap != null) { + bitmap.Dispose (); + bitmap = null; + } + } + + public virtual PropertyDescriptor GetDefaultProperty (object component) + { + return TypeDescriptor.GetDefaultProperty(component); + } + + public virtual PropertyDescriptorCollection GetProperties (object component) + { + return GetProperties (component, null); + } + + public abstract PropertyDescriptorCollection GetProperties (object component, Attribute[] attributes); + + public virtual PropertyDescriptorCollection GetProperties (ITypeDescriptorContext context, object component, Attribute[] attributes) + { + return GetProperties (component, attributes); + } + } +} diff --git a/source/ShiftUI/Design/ScrollableControlDesigner.cs b/source/ShiftUI/Design/ScrollableControlDesigner.cs new file mode 100644 index 0000000..fb49f9a --- /dev/null +++ b/source/ShiftUI/Design/ScrollableControlDesigner.cs @@ -0,0 +1,83 @@ +// +// ShiftUI.Design.ScrollableWidgetDesigner +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; + + + +namespace ShiftUI.Design +{ + + public class ScrollableWidgetDesigner : ParentWidgetDesigner + { + + public ScrollableWidgetDesigner () + { + } + + private const int HTHSCROLL = 6; + private const int HTVSCROLL = 7; + + protected override bool GetHitTest (Point point) + { + if (base.GetHitTest (point)) { + return true; + } + + // Check if the user has clicked on the scroll bars and forward the message to + // the ScrollableWidget. (Don't filter out the scrolling.). Keep in mind that scrollbars + // will be shown only if ScrollableWidget.AutoScroll = true + // + if (this.Widget is ScrollableWidget && ((ScrollableWidget)Widget).AutoScroll) { + int hitTestResult = (int) Native.SendMessage (this.Widget.Handle, + Native.Msg.WM_NCHITTEST, + IntPtr.Zero, + (IntPtr) Native.LParam (point.X, point.Y)); + if (hitTestResult == HTHSCROLL || hitTestResult == HTVSCROLL) + return true; + } + return false; + } + + + protected override void WndProc (ref Message m) + { + base.WndProc (ref m); + if (m.Msg == (int)Native.Msg.WM_HSCROLL || m.Msg == (int)Native.Msg.WM_VSCROLL) + this.DefWndProc (ref m); + } + } +} diff --git a/source/ShiftUI/Design/SelectionFrame.cs b/source/ShiftUI/Design/SelectionFrame.cs new file mode 100644 index 0000000..a3c092d --- /dev/null +++ b/source/ShiftUI/Design/SelectionFrame.cs @@ -0,0 +1,481 @@ +// +// ShiftUI.Design.SelectionFrame +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Drawing.Drawing2D; +using ShiftUI; + + +namespace ShiftUI.Design +{ + // This is not a control! + // + internal class SelectionFrame + { + + public SelectionFrame (Widget control) + { + if (control == null) + throw new ArgumentNullException ("control"); + + _control = control; + } + + + private Rectangle _bounds; + private Widget _control; + private Rectangle[] _handles = new Rectangle[8]; + private GrabHandle _handle = GrabHandle.None; + private const int BORDER_SIZE = 7; + + +#region Properties + private enum GrabHandle { + None = -1, + TopLeft = 0, + TopMiddle, + TopRight, + Right, + BottomRight, + BottomMiddle, + BottomLeft, + Left, + Border // the border surrounding the control. + } + + public Rectangle Bounds { + get { + _bounds.X = _control.Location.X - BORDER_SIZE; + _bounds.Y = _control.Location.Y - BORDER_SIZE; + _bounds.Width = _control.Width + BORDER_SIZE *2; + _bounds.Height = _control.Height + BORDER_SIZE *2; + + return _bounds; + } + set { + _bounds = value; + _control.Bounds = _bounds; + } + } + + private SelectionRules SelectionRules { + get { + SelectionRules result = SelectionRules.AllSizeable; + + if (_control.Site != null) { + IDesignerHost host = _control.Site.GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host != null) { + WidgetDesigner designer = host.GetDesigner (_control) as WidgetDesigner; + if (designer != null) + result = designer.SelectionRules; + } + } + + return result; + } + } + + public Widget Widget { + get { return _control; } + set { + if (value != null) + _control = value; + } + } + + public Widget Parent { + get { + if (_control.Parent == null) + return _control; + else + return _control.Parent; + } + } + + private GrabHandle GrabHandleSelected { + get { return _handle; } + set { _handle = value; } + } + + private bool PrimarySelection{ + get { + bool result = false; + if (this.Widget != null && this.Widget.Site != null) { + ISelectionService selection = this.Widget.Site.GetService (typeof (ISelectionService)) as ISelectionService; + if (selection != null && selection.PrimarySelection == this.Widget) + result = true; + } + return result; + } + } +#endregion + + +#region Drawing + public void OnPaint (Graphics gfx) + { + DrawFrame (gfx); + DrawGrabHandles (gfx); + } + + private void DrawGrabHandles (Graphics gfx) + { + GraphicsState state = gfx.Save(); + gfx.TranslateTransform (this.Bounds.X, this.Bounds.Y); + + for (int i = 0; i < _handles.Length; i++) { + _handles[i].Width = BORDER_SIZE; + _handles[i].Height = BORDER_SIZE; + } + + SelectionRules rules = this.SelectionRules; + bool primarySelection = this.PrimarySelection; + bool enabled = false; + + _handles[(int) GrabHandle.TopLeft].Location = new Point (0,0); + if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.LeftSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopLeft], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.TopMiddle].Location = new Point ((this.Bounds.Width - BORDER_SIZE) / 2, 0); + if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopMiddle], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.TopRight].Location = new Point (this.Bounds.Width - BORDER_SIZE, 0); + if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.RightSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopRight], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.Right].Location = new Point (this.Bounds.Width - BORDER_SIZE, + (this.Bounds.Height - BORDER_SIZE) / 2); + if (this.CheckSelectionRules (rules, SelectionRules.RightSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.Right], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.BottomRight].Location = new Point (this.Bounds.Width - BORDER_SIZE, + this.Bounds.Height - BORDER_SIZE); + if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.RightSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomRight], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.BottomMiddle].Location = new Point ((this.Bounds.Width - BORDER_SIZE) / 2, + this.Bounds.Height - BORDER_SIZE); + if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomMiddle], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.BottomLeft].Location = new Point (0, this.Bounds.Height - BORDER_SIZE); + if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.LeftSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomLeft], primarySelection, enabled); + enabled = false; + + _handles[(int) GrabHandle.Left].Location = new Point (0, (this.Bounds.Height - BORDER_SIZE) / 2); + if (this.CheckSelectionRules (rules, SelectionRules.LeftSizeable)) + enabled = true; + + WidgetPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.Left], primarySelection, enabled); + gfx.Restore (state); + } + + protected void DrawFrame (Graphics gfx) + { + Color negativeColor = Color.FromArgb ((byte)~(_control.Parent.BackColor.R), + (byte)~(_control.Parent.BackColor.G), + (byte)~(_control.Parent.BackColor.B)); + Pen pen = new Pen (new HatchBrush (HatchStyle.Percent30, negativeColor, Color.FromArgb (0)), BORDER_SIZE); + gfx.DrawRectangle (pen, this.Widget.Bounds); + } +#endregion + + +#region Dragging + private bool _resizing = false; + + + public bool SetCursor (int x, int y) + { + bool modified = false; + + if (!_resizing) { + GrabHandle handle = PointToGrabHandle (this.PointToClient (Widget.MousePosition)); + if (handle != GrabHandle.None) + modified = true; + + if (handle == GrabHandle.TopLeft) + Cursor.Current = Cursors.SizeNWSE; + else if (handle == GrabHandle.TopMiddle) + Cursor.Current = Cursors.SizeNS; + else if (handle == GrabHandle.TopRight) + Cursor.Current = Cursors.SizeNESW; + else if (handle == GrabHandle.Right) + Cursor.Current = Cursors.SizeWE; + else if (handle == GrabHandle.BottomRight) + Cursor.Current = Cursors.SizeNWSE; + else if (handle == GrabHandle.BottomMiddle) + Cursor.Current = Cursors.SizeNS; + else if (handle == GrabHandle.BottomLeft) + Cursor.Current = Cursors.SizeNESW; + else if (handle == GrabHandle.Left) + Cursor.Current = Cursors.SizeWE; + else + Cursor.Current = Cursors.Default; + } + return modified; + } + + // container coordinates + public void ResizeBegin (int x, int y) + { + this.GrabHandleSelected = PointToGrabHandle (this.PointToClient (this.Parent.PointToScreen (new Point (x, y)))); + + if (this.GrabHandleSelected != GrabHandle.None) + _resizing = true; + } + + private bool CheckSelectionRules (SelectionRules rules, SelectionRules toCheck) + { + return ((rules & toCheck) == toCheck); + } + + // container coordinates returns deltaBounds + public Rectangle ResizeContinue (int x, int y) + { + //Console.WriteLine ("ResizeContinue: " + x + " : " + y); + //Console.WriteLine ("GrabHandleSelected: " + GrabHandleSelected); + + Rectangle bounds = (Rectangle)TypeDescriptor.GetProperties (_control)["Bounds"].GetValue (_control); + Rectangle deltaBounds = bounds; + Point pointerLocation = new Point (x, y); + SelectionRules rules = this.SelectionRules; + int top, height, left, width = 0; + + if (_resizing && this.GrabHandleSelected != GrabHandle.None && rules != SelectionRules.Locked) { + if (this.GrabHandleSelected == GrabHandle.TopLeft && + CheckSelectionRules (rules, SelectionRules.LeftSizeable | SelectionRules.TopSizeable)) { + + top = _control.Top; + height = _control.Height; + left = _control.Left; + width = _control.Width; + + if (pointerLocation.Y < _control.Bottom) { + top = pointerLocation.Y; + height = _control.Bottom - pointerLocation.Y; + } + if (pointerLocation.X < _control.Right) { + left = pointerLocation.X; + width = _control.Right - pointerLocation.X; + bounds = new Rectangle (left, top, width, height); + } + } + else if (this.GrabHandleSelected == GrabHandle.TopRight && + CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.RightSizeable)) { + + top = _control.Top; + height = _control.Height; + width = _control.Width; + + if (pointerLocation.Y < _control.Bottom) { + top = pointerLocation.Y; + height = _control.Bottom - pointerLocation.Y; + } + width = pointerLocation.X - _control.Left; + bounds = new Rectangle (_control.Left, top, width, height); + } + else if (GrabHandleSelected == GrabHandle.TopMiddle && CheckSelectionRules (rules, SelectionRules.TopSizeable)) { + if (pointerLocation.Y < _control.Bottom) { + top = pointerLocation.Y; + height = _control.Bottom - pointerLocation.Y; + bounds = new Rectangle (_control.Left, top, _control.Width, height); + } + } + else if (this.GrabHandleSelected == GrabHandle.Right && CheckSelectionRules (rules, SelectionRules.RightSizeable)) { + width = pointerLocation.X - _control.Left; + bounds = new Rectangle (_control.Left, _control.Top, width, _control.Height); + } + else if (this.GrabHandleSelected == GrabHandle.BottomRight && + CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.RightSizeable)) { + + width = pointerLocation.X - _control.Left; + height = pointerLocation.Y - _control.Top; + bounds = new Rectangle (_control.Left, _control.Top, width, height); + } + else if (GrabHandleSelected == GrabHandle.BottomMiddle && CheckSelectionRules (rules, SelectionRules.BottomSizeable)) { + height = pointerLocation.Y - _control.Top; + bounds = new Rectangle (_control.Left, _control.Top, _control.Width, height); + } + else if (GrabHandleSelected == GrabHandle.BottomLeft && + CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.LeftSizeable)) { + + height = _control.Height; + left = _control.Left; + width = _control.Width; + + if (pointerLocation.X < _control.Right) { + left = pointerLocation.X; + width = _control.Right - pointerLocation.X; + } + height = pointerLocation.Y - _control.Top; + bounds = new Rectangle (left, _control.Top, width, height); + } + else if (GrabHandleSelected == GrabHandle.Left && CheckSelectionRules (rules, SelectionRules.LeftSizeable)) { + if (pointerLocation.X < _control.Right) { + left = pointerLocation.X; + width = _control.Right - pointerLocation.X; + bounds = new Rectangle (left, _control.Top, width, _control.Height); + } + } + + //Console.WriteLine ("bounds: " + bounds.ToString ()); + TypeDescriptor.GetProperties (_control)["Bounds"].SetValue (_control, bounds); + + } + + this.Parent.Refresh (); + deltaBounds.X = bounds.X - deltaBounds.X; + deltaBounds.Y = bounds.Y - deltaBounds.Y; + deltaBounds.Height = bounds.Height - deltaBounds.Height; + deltaBounds.Width = bounds.Width - deltaBounds.Width; + return deltaBounds; + } + + + public void ResizeEnd (bool cancel) + { + this.GrabHandleSelected = GrabHandle.None; + _resizing = false; + } + + public void Resize (Rectangle deltaBounds) + { + SelectionRules rules = this.SelectionRules; + + if (this.CheckSelectionRules (rules, SelectionRules.Locked) || !this.CheckSelectionRules (rules, SelectionRules.Moveable)) + return; + + Rectangle bounds = (Rectangle)TypeDescriptor.GetProperties (_control)["Bounds"].GetValue (_control); + + if (CheckSelectionRules (rules, SelectionRules.LeftSizeable)) { + bounds.X += deltaBounds.X; + bounds.Width += deltaBounds.Width; + } + if (CheckSelectionRules (rules, SelectionRules.RightSizeable) && !CheckSelectionRules (rules, SelectionRules.LeftSizeable)) { + bounds.Y += deltaBounds.Y; + bounds.Width += deltaBounds.Width; + } + if (CheckSelectionRules (rules, SelectionRules.TopSizeable)) { + bounds.Y += deltaBounds.Y; + bounds.Height += deltaBounds.Height; + } + if (CheckSelectionRules (rules, SelectionRules.BottomSizeable) && !CheckSelectionRules (rules, SelectionRules.TopSizeable)) { + bounds.Height += deltaBounds.Height; + } + + TypeDescriptor.GetProperties (_control)["Bounds"].SetValue (_control, bounds); + } +#endregion + + +#region Utility methods + + public bool HitTest (int x, int y) + { + if (PointToGrabHandle (this.PointToClient (this.Parent.PointToScreen (new Point (x, y)))) != GrabHandle.None) + return true; + else + return false; + } + + private GrabHandle PointToGrabHandle (Point pointerLocation) + { + GrabHandle result = GrabHandle.None; + + if (IsCursorOnGrabHandle (pointerLocation, _handles[0])) + result = GrabHandle.TopLeft; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[1])) + result = GrabHandle.TopMiddle; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[2])) + result = GrabHandle.TopRight; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[3])) + result = GrabHandle.Right; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[4])) + result = GrabHandle.BottomRight; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[5])) + result = GrabHandle.BottomMiddle; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[6])) + result = GrabHandle.BottomLeft; + else if (IsCursorOnGrabHandle (pointerLocation, _handles[7])) + result = GrabHandle.Left; + else + result = GrabHandle.None; + + return result; + } + + private bool IsCursorOnGrabHandle (Point pointerLocation, Rectangle handleRectangle) + { + if (pointerLocation.X >= handleRectangle.X && + pointerLocation.X <= handleRectangle.X + handleRectangle.Width && + pointerLocation.Y >= handleRectangle.Y && + pointerLocation.Y <= handleRectangle.Y + handleRectangle.Height) { + return true; + } + return false; + } + + private Point PointToClient (Point screenPoint) + { + Point pointerLocation = this.Parent.PointToClient (screenPoint); + pointerLocation.X = pointerLocation.X - this.Bounds.X; + pointerLocation.Y = pointerLocation.Y - this.Bounds.Y; + return pointerLocation; + } +#endregion + + } +} diff --git a/source/ShiftUI/Design/SelectionRules.cs b/source/ShiftUI/Design/SelectionRules.cs new file mode 100644 index 0000000..84e5a41 --- /dev/null +++ b/source/ShiftUI/Design/SelectionRules.cs @@ -0,0 +1,47 @@ +// +// ShiftUI.Design.SelectionRules.cs +// +// Author: +// Gert Driesen ([email protected]) +// (C) 2004 Ximian, Inc. http://www.ximian.com +// + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace ShiftUI.Design +{ + [Flags] + public enum SelectionRules + { + AllSizeable = 15, + BottomSizeable = 2, + LeftSizeable = 4, + Locked = -2147483648, + Moveable = 268435456, + None = 0, + RightSizeable = 8, + TopSizeable = 1, + Visible = 1073741824 + } +} diff --git a/source/ShiftUI/Design/ToolStripItemDesignerAvailability.cs b/source/ShiftUI/Design/ToolStripItemDesignerAvailability.cs new file mode 100644 index 0000000..5452d15 --- /dev/null +++ b/source/ShiftUI/Design/ToolStripItemDesignerAvailability.cs @@ -0,0 +1,43 @@ +// +// ToolStripItemDesignerAvailability.cs +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) Jonathan Pobst +// +// Authors: +// Jonathan Pobst ([email protected]) +// + +using System; + +namespace ShiftUI.Design +{ + [Flags] + public enum ToolStripItemDesignerAvailability + { + None = 0, + ToolStrip = 1, + MenuStrip = 2, + ContextMenuStrip = 4, + StatusStrip = 8, + All = 15 + } +} diff --git a/source/ShiftUI/Design/ToolStripItemDesignerAvailabilityAttribute.cs b/source/ShiftUI/Design/ToolStripItemDesignerAvailabilityAttribute.cs new file mode 100644 index 0000000..f5ca759 --- /dev/null +++ b/source/ShiftUI/Design/ToolStripItemDesignerAvailabilityAttribute.cs @@ -0,0 +1,81 @@ +// +// ToolStripItemDesignerAvailabilityAttribute.cs +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) Jonathan Pobst +// +// Authors: +// Jonathan Pobst ([email protected]) +// + +using System; +using System.Collections.Generic; +using System.Text; + +namespace ShiftUI.Design +{ + [AttributeUsage (AttributeTargets.Class)] + public sealed class ToolStripItemDesignerAvailabilityAttribute : Attribute + { + private ToolStripItemDesignerAvailability visibility; + public static readonly ToolStripItemDesignerAvailabilityAttribute Default = new ToolStripItemDesignerAvailabilityAttribute (); + + #region Public Constructors + public ToolStripItemDesignerAvailabilityAttribute () + : base () + { + this.visibility = ToolStripItemDesignerAvailability.None; + } + + public ToolStripItemDesignerAvailabilityAttribute (ToolStripItemDesignerAvailability visibility) + : base () + { + this.visibility = visibility; + } + #endregion + + #region Public Properties + public ToolStripItemDesignerAvailability ItemAdditionVisibility { + get { return this.visibility; } + } + #endregion + + #region Public Methods + public override bool Equals (object obj) + { + if (!(obj is ToolStripItemDesignerAvailabilityAttribute)) + return false; + + return this.ItemAdditionVisibility == (obj as ToolStripItemDesignerAvailabilityAttribute).ItemAdditionVisibility; + } + + public override int GetHashCode () + { + return (int)this.visibility; + } + + public override bool IsDefaultAttribute () + { + return this.visibility == ToolStripItemDesignerAvailability.None; + } + #endregion + } +} diff --git a/source/ShiftUI/Design/UISelectionService.cs b/source/ShiftUI/Design/UISelectionService.cs new file mode 100644 index 0000000..78a722b --- /dev/null +++ b/source/ShiftUI/Design/UISelectionService.cs @@ -0,0 +1,532 @@ +// +// ShiftUI.Design.UISelectionService +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.Collections; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Drawing.Drawing2D; +using ShiftUI; + +namespace ShiftUI.Design +{ + + internal class UISelectionService : IUISelectionService + { + + private IServiceProvider _serviceProvider; + private DesignerTransaction _transaction; + private ISelectionService _selectionService; + + public UISelectionService (IServiceProvider serviceProvider) + { + if (serviceProvider == null) + throw new ArgumentNullException ("serviceProvider"); + + _serviceProvider = serviceProvider; + _transaction = null; + + _selectionService = serviceProvider.GetService (typeof (ISelectionService)) as ISelectionService; + if (_selectionService == null) { + IServiceContainer serviceContainer = serviceProvider.GetService (typeof (IServiceContainer)) as IServiceContainer; + _selectionService = new UISelectionService (serviceContainer) as ISelectionService; + serviceContainer.AddService (typeof (ISelectionService), (ISelectionService) _selectionService); + } + + _selectionService.SelectionChanged += new EventHandler (OnSelectionChanged); + } + + private ISelectionService SelectionService { + get { return _selectionService; } + } + + private object GetService (Type service) + { + return _serviceProvider.GetService (service); + } + + public bool SelectionInProgress { + get { return _selecting; } + } + + public bool DragDropInProgress { + get { return _dragging; } + } + + public bool ResizeInProgress{ + get { return _resizing; } + } + + + public bool SetCursor (int x, int y) + { + bool modified = false; + // if moving mouse around - set cursor if mouse is hovering a selectionframes' grabhandles + // + SelectionFrame frame = GetSelectionFrameAt (x, y); + if (frame != null && frame.HitTest (x, y) && frame.SetCursor (x, y)) + modified = true; + + return modified; + } + + + public void MouseDragBegin (Widget container, int x, int y) + { + // * start resizing the selection frame + // * start selecting + // + SelectionFrame frame = GetSelectionFrameAt (x, y); + + if (frame != null && frame.HitTest (x, y)) { + this.SelectionService.SetSelectedComponents (new IComponent[] { frame.Widget }); + if (_transaction == null) { + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + _transaction = host.CreateTransaction ("Resize " + + (this.SelectionService.SelectionCount == 1 ? ((IComponent)this.SelectionService.PrimarySelection).Site.Name : "controls")); + } + this.ResizeBegin (x, y); + } + else { + SelectionBegin (container, x, y); + } + } + + public void MouseDragMove (int x, int y) + { + if (_selecting) + SelectionContinue (x, y); + else if (_resizing) + ResizeContinue (x, y); + } + + public void MouseDragEnd (bool cancel) + { + if (_selecting) + SelectionEnd (cancel); + else if (_resizing) { + ResizeEnd (cancel); + if (_transaction != null) { + if (cancel) + _transaction.Cancel (); + else + _transaction.Commit (); + _transaction = null; + } + } + + if (Cursor.Current != Cursors.Default) + Cursor.Current = Cursors.Default; + } + + +#region Dragging + private bool _dragging = false; + private Point _prevMousePosition; + private bool _firstMove = false; + + // container coordinates (primary selection's) + // + public void DragBegin () + { + // Console.WriteLine ("DragBegin"); + if (_transaction == null) { + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + _transaction = host.CreateTransaction ("Move " + + (this.SelectionService.SelectionCount == 1? ((IComponent)this.SelectionService.PrimarySelection).Site.Name : "controls")); + } + _dragging = true; + _firstMove = true; + if (this.SelectionService.PrimarySelection != null) + ((Widget)this.SelectionService.PrimarySelection).DoDragDrop (new WidgetDataObject ((Widget)this.SelectionService.PrimarySelection), DragDropEffects.All); + } + + // container cordinates + // + public void DragOver (Widget container, int x, int y) + { + // Console.WriteLine ("DragOver"); + if (_dragging) { + if (_firstMove) { + _prevMousePosition = new Point (x, y); + _firstMove = false; + } + else { + int dx = x - _prevMousePosition.X; + int dy = y - _prevMousePosition.Y; + MoveSelection (container, dx, dy); + _prevMousePosition = new Point (x, y); + + // Repaint everything >_< + // + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host != null && host.RootComponent != null) + ((Widget)host.RootComponent).Refresh (); + //container.Refresh (); + } + } + } + + // container coordinates + // + public void DragDrop (bool cancel, Widget container, int x, int y) + { + // Console.WriteLine ("UISelectionService.DragDrop: in " + container.Site.Name); + if (_dragging) { + int dx = x - _prevMousePosition.X; + int dy = y - _prevMousePosition.Y; + + MoveSelection (container, dx, dy); + _dragging = false; + + // Repaint everything + // + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + if (host != null && host.RootComponent != null) + ((Widget)host.RootComponent).Refresh (); + // Send mouse up message to the primary selection + // Else for parentcontroldesigner there is no mouseup event and it doesn't set allow drop back to false + // + Native.SendMessage (((Widget)this.SelectionService.PrimarySelection).Handle, Native.Msg.WM_LBUTTONUP, (IntPtr) 0, (IntPtr) 0); + if (_transaction != null) { + if (cancel) + _transaction.Cancel (); + else + _transaction.Commit (); + _transaction = null; + } + } + } + + private void MoveSelection (Widget container, int dx, int dy) + { + bool reparent = false; + Widget oldParent = null; + + if (((Widget)this.SelectionService.PrimarySelection).Parent != container && !this.SelectionService.GetComponentSelected (container)) { + reparent = true; + oldParent = ((Widget)this.SelectionService.PrimarySelection).Parent; + } + + // FIXME: Should check selectionstyle per control to determine if it's locked... + // if locked -> don't move + // + ICollection selection = this.SelectionService.GetSelectedComponents (); + foreach (Component component in selection) { + Widget control = component as Widget; + if (reparent) + TypeDescriptor.GetProperties (control)["Parent"].SetValue (control, container); + + PropertyDescriptor property = TypeDescriptor.GetProperties (control)["Location"]; + Point location = (Point) property.GetValue (control); + location.X += dx; + location.Y += dy; + property.SetValue (control, location); + } + + if (reparent) { + oldParent.Invalidate (false); + oldParent.Update (); + } + } +#endregion + + +#region Selection + + private bool _selecting = false; + private Widget _selectionContainer = null; + private Point _initialMousePosition; + private Rectangle _selectionRectangle; + // XXX + private ArrayList _selectionFrames = new ArrayList (); + + + public Rectangle SelectionBounds { + get { return _selectionRectangle; } + } + + // container coordinates + // + private void SelectionBegin (Widget container, int x, int y) + { + // Console.WriteLine ("SelectionBegin"); + _selecting = true; + _selectionContainer = container; + _prevMousePosition = new Point (x, y); + _initialMousePosition = _prevMousePosition; + _selectionRectangle = new Rectangle (x , y, 0, 0); + } + + private void SelectionContinue (int x, int y) + { + // Console.WriteLine ("SelectionContinue"); + if (_selecting) { + // right to right + // + if (x > _selectionRectangle.Right) { + _selectionRectangle.Width = x - _selectionRectangle.X; + } + // right to left + else if (x > _selectionRectangle.X && x < _selectionRectangle.Right && + x < _prevMousePosition.X) { + + _selectionRectangle.Width = x - _selectionRectangle.X; + } + // left to left - f + else if (x < _selectionRectangle.X) { + + // hasn't flipped + if (_prevMousePosition.X > _selectionRectangle.X) { + _selectionRectangle.X = _initialMousePosition.X; + _selectionRectangle.Width = 0; + } + else { + _selectionRectangle.Width += _selectionRectangle.X - x; + _selectionRectangle.X = x; + } + } + // left to right - f + else if (x > _selectionRectangle.X && x < _selectionRectangle.Right && + x > _prevMousePosition.X) { + + if (_prevMousePosition.X < _selectionRectangle.X) { + _selectionRectangle.X = _initialMousePosition.X; + _selectionRectangle.Width = 0; + } + else { + _selectionRectangle.Width -= x - _selectionRectangle.X; + _selectionRectangle.X = x; + } + } + + + if (y > _selectionRectangle.Bottom) { + _selectionRectangle.Height = y - _selectionRectangle.Y; + } + else if (y > _selectionRectangle.Y && y < _selectionRectangle.Bottom && + y < _prevMousePosition.Y) { + + _selectionRectangle.Height = y - _selectionRectangle.Y; + + } + else if (y < _selectionRectangle.Y) { + if (_prevMousePosition.Y > _selectionRectangle.Y) { + _selectionRectangle.Y = _initialMousePosition.Y; + _selectionRectangle.Height = 0; + } + else { + _selectionRectangle.Height += _selectionRectangle.Y - y; + _selectionRectangle.Y = y; + } + } + else if (y > _selectionRectangle.Y && y < _selectionRectangle.Bottom && + y > _prevMousePosition.Y) { + + if (_prevMousePosition.Y < _selectionRectangle.Y) { + _selectionRectangle.Y = _initialMousePosition.Y; + _selectionRectangle.Height = 0; + } + else { + _selectionRectangle.Height -= y - _selectionRectangle.Y; + _selectionRectangle.Y = y; + } + } + + _prevMousePosition.X = x; + _prevMousePosition.Y = y; + + _selectionContainer.Refresh (); + } + } + + private void SelectionEnd (bool cancel) + { + // Console.WriteLine ("SelectionEnd"); + _selecting = false; + ICollection selectedWidgets = GetWidgetsIn (_selectionRectangle); + // do not change selection if nothing has changed + // + if (selectedWidgets.Count != 0) + this.SelectionService.SetSelectedComponents (selectedWidgets, SelectionTypes.Replace); + + _selectionContainer.Refresh (); + } +#endregion + + +#region Resizing + private SelectionFrame _selectionFrame; + private bool _resizing = false; + + private void ResizeBegin (int x, int y) + { + // Console.WriteLine ("ResizeBegin"); + _resizing = true; + _selectionFrame = this.GetSelectionFrameAt (x, y); + _selectionFrame.ResizeBegin (x, y); + } + + private void ResizeContinue (int x, int y) + { + // Console.WriteLine ("ResizeContinue"); + Rectangle deltaBounds = _selectionFrame.ResizeContinue (x, y); + ICollection selection = this.SelectionService.GetSelectedComponents (); + + foreach (IComponent component in selection) { + if (component is Widget) { + SelectionFrame frame = GetSelectionFrameFor ((Widget)component); + if (frame != _selectionFrame) + frame.Resize (deltaBounds); + } + } + + } + + private void ResizeEnd (bool cancel) + { + // Console.WriteLine ("ResizeEnd"); + _selectionFrame.ResizeEnd (cancel); + _resizing = false; + } + + + private SelectionFrame GetSelectionFrameAt (int x, int y) + { + SelectionFrame result = null; + + foreach (SelectionFrame frame in _selectionFrames) { + if (frame.Bounds.Contains (new Point (x, y))) { + result = frame; + break; + } + } + + return result; + } + + private SelectionFrame GetSelectionFrameFor (Widget control) + { + foreach (SelectionFrame frame in _selectionFrames) { + if (control == frame.Widget) + return frame; + } + return null; + } +#endregion + + public bool AdornmentsHitTest (Widget control, int x, int y) + { + SelectionFrame frame = GetSelectionFrameAt (x, y); + if (frame != null) + return frame.HitTest (x, y); + + return false; + } + + // This method is called by all ParentWidgetDesigner.OnPaintAdornments. + // Selection frames are drawn in the parent container of the primary selection + // selection rectangle is drawn in the primary selection + // + public void PaintAdornments (Widget container, Graphics gfx) + { + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + + if (host == null || !(this.SelectionService.PrimarySelection is Widget)) + return; + + if ((Widget)this.SelectionService.PrimarySelection == container) { + if (_selecting) { + Color negativeColor = Color.FromArgb ((byte)~(_selectionContainer.BackColor.R), + (byte)~(_selectionContainer.BackColor.G), + (byte)~(_selectionContainer.BackColor.B)); + DrawSelectionRectangle (gfx, _selectionRectangle, negativeColor); + } + } + else if (((Widget)this.SelectionService.PrimarySelection).Parent == container) { + foreach (SelectionFrame frame in _selectionFrames) + frame.OnPaint (gfx); + } + } + + + private void DrawSelectionRectangle (Graphics gfx, Rectangle frame, Color color) + { + Pen pen = new Pen (color); + pen.DashStyle = DashStyle.Dash; + gfx.DrawRectangle (pen, frame); + } + + + private void OnSelectionChanged (object sender, EventArgs args) + { + ICollection selection = this.SelectionService.GetSelectedComponents (); + + if (_selectionFrames.Count == 0) { + foreach (Component component in selection) { + _selectionFrames.Add (new SelectionFrame ((Widget) component)); + } // this code should get executed only once! (when initial primary selection is set) + } else { + int i = 0; + foreach (Component component in selection) { + if (i >= _selectionFrames.Count) + _selectionFrames.Add (new SelectionFrame ((Widget) component)); + else + ((SelectionFrame)_selectionFrames[i]).Widget = (Widget) component; + i++; + } + if (i < _selectionFrames.Count) + _selectionFrames.RemoveRange (i, _selectionFrames.Count - i); + } + // Refresh the whole design surface (including the view) + // + IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost; + Widget root = host.RootComponent as Widget; + if (root != null) { + if (root.Parent != null) + root.Parent.Refresh (); + else + root.Refresh (); + } + } + + private ICollection GetWidgetsIn (Rectangle rect) + { + ArrayList selectedWidgets = new ArrayList (); + + foreach (Widget control in _selectionContainer.Widgets) { + if (rect.Contains (control.Bounds) || rect.IntersectsWith (control.Bounds)) + selectedWidgets.Add (control); + } + return selectedWidgets; + } + + } +} diff --git a/source/ShiftUI/Design/WindowsFormsComponentEditor.cs b/source/ShiftUI/Design/WindowsFormsComponentEditor.cs new file mode 100644 index 0000000..9dbfc7a --- /dev/null +++ b/source/ShiftUI/Design/WindowsFormsComponentEditor.cs @@ -0,0 +1,65 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// 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) 2004 Novell, Inc. +// +// Authors: +// Andreas Nahr ([email protected]) +// + +using System.ComponentModel; +using System; + +namespace ShiftUI.Design +{ + public abstract class WindowsFormsComponentEditor : ComponentEditor + { + protected WindowsFormsComponentEditor () + { + } + + public override bool EditComponent (ITypeDescriptorContext context, object component) + { + return EditComponent (context, component, null); + } + + public virtual bool EditComponent (ITypeDescriptorContext context, object component, IWin32Window owner) + { + ComponentEditorForm f = new ComponentEditorForm (component, GetComponentEditorPages ()); + if (f.ShowForm (owner, GetInitialComponentEditorPageIndex ()) == DialogResult.OK) + return true; + return false; + } + + public bool EditComponent (object component, IWin32Window owner) + { + return EditComponent (null, component, owner); + } + + protected virtual Type[] GetComponentEditorPages () + { + return null; + } + + protected virtual int GetInitialComponentEditorPageIndex () + { + return 0; + } + } +} diff --git a/source/ShiftUI/Design/WndProcRouter.cs b/source/ShiftUI/Design/WndProcRouter.cs new file mode 100644 index 0000000..83c3f1d --- /dev/null +++ b/source/ShiftUI/Design/WndProcRouter.cs @@ -0,0 +1,117 @@ +// +// ShiftUI.Design.WndProcRouter +// +// Authors: +// Ivan N. Zlatev (contact i-nZ.net) +// +// (C) 2006-2007 Ivan N. Zlatev + +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using ShiftUI; +using System.Drawing; +using System.Drawing.Design; +using System.Collections; + + // Automatically reroutes Messages to the designer + // + +namespace ShiftUI.Design +{ + + internal class WndProcRouter : IWindowTarget, IDisposable + { + private IWindowTarget _oldTarget; + private IMessageReceiver _receiver; + private Widget _control; + + public WndProcRouter (Widget control, IMessageReceiver receiver) + { + if (control == null) + throw new ArgumentNullException ("control"); + if (receiver == null) + throw new ArgumentNullException ("receiver"); + + _oldTarget = control.WindowTarget; + _control = control; + _receiver = receiver; + } + + public Widget Widget { + get { return _control; } + } + + public IWindowTarget OldWindowTarget { + get { return _oldTarget; } + } + + // Route the message to the control + // + public void ToWidget (ref Message m) + { + //Console.WriteLine ("Widget: " + ((Native.Msg)m.Msg).ToString ()); + if (_oldTarget != null) + _oldTarget.OnMessage (ref m); + } + + public void ToSystem (ref Message m) + { + //Console.WriteLine ("System: " + ((Native.Msg)m.Msg).ToString ()); + Native.DefWndProc (ref m); + } + + // Just pass it to the old IWindowTarget + // + void IWindowTarget.OnHandleChange (IntPtr newHandle) + { + if (_oldTarget != null) + _oldTarget.OnHandleChange (newHandle); + } + + // Route the msg to the designer if available, else to + // control itself. + // + void IWindowTarget.OnMessage (ref Message m) + { + //Console.WriteLine ("Message: " + ((Native.Msg)m.Msg).ToString ()); + if (_receiver != null) + _receiver.WndProc (ref m); + else + this.ToWidget (ref m); + } + + // Disposes and puts back the old IWindowTarget + // + public void Dispose () + { + if (_control != null) + _control.WindowTarget = _oldTarget; + + _control = null; + _oldTarget = null; + } + + } +} |
