Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/ShadedContainer.cs')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/ShadedContainer.cs314
1 files changed, 314 insertions, 0 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/ShadedContainer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/ShadedContainer.cs
new file mode 100644
index 0000000000..f8d20a906e
--- /dev/null
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/ShadedContainer.cs
@@ -0,0 +1,314 @@
+//
+// ShadedContainer.cs
+//
+// Author:
+// Lluis Sanchez Gual <lluis@novell.com>
+//
+// Copyright (c) 2010 Novell, Inc (http://www.novell.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;
+using System.Collections.Generic;
+using Gtk;
+using MonoDevelop.Components;
+
+namespace MonoDevelop.Components.Docking
+{
+ public class ShadedContainer
+ {
+ struct Section {
+ public int Offset;
+ public int Size;
+ }
+
+ Gdk.Color lightColor;
+ Gdk.Color darkColor;
+ int shadowSize = 2;
+
+ List<Widget> widgets = new List<Widget> ();
+ Dictionary<Widget, Gdk.Rectangle[]> allocations = new Dictionary<Widget, Gdk.Rectangle[]> ();
+
+ public ShadedContainer ()
+ {
+ }
+
+ public int ShadowSize {
+ get { return this.shadowSize; }
+ set { this.shadowSize = value; RedrawAll (); }
+ }
+
+ public Gdk.Color LightColor {
+ get { return this.lightColor; }
+ set { this.lightColor = value; RedrawAll (); }
+ }
+
+ public Gdk.Color DarkColor {
+ get { return this.darkColor; }
+ set { this.darkColor = value; RedrawAll (); }
+ }
+
+ public void Add (Gtk.Widget w)
+ {
+ widgets.Add (w);
+ UpdateAllocation (w);
+ w.Destroyed += HandleWDestroyed;
+ w.Shown += HandleWShown;
+ w.Hidden += HandleWHidden;
+ w.SizeAllocated += HandleWSizeAllocated;
+ IShadedWidget sw = w as IShadedWidget;
+ if (sw != null)
+ sw.AreasChanged += HandleSwAreasChanged;
+ RedrawAll ();
+ }
+
+ public void Remove (Widget w)
+ {
+ widgets.Remove (w);
+ allocations.Remove (w);
+ w.Destroyed -= HandleWDestroyed;
+ w.Shown -= HandleWShown;
+ w.Hidden -= HandleWHidden;
+ IShadedWidget sw = w as IShadedWidget;
+ if (sw != null)
+ sw.AreasChanged -= HandleSwAreasChanged;
+ RedrawAll ();
+ }
+
+ void UpdateAllocation (Widget w)
+ {
+ if (w.IsRealized) {
+ int x, y;
+ w.GdkWindow.GetOrigin (out x, out y);
+ IShadedWidget sw = w as IShadedWidget;
+ if (sw != null) {
+ List<Gdk.Rectangle> rects = new List<Gdk.Rectangle> ();
+ foreach (Gdk.Rectangle ar in sw.GetShadedAreas ()) {
+ Gdk.Rectangle r = new Gdk.Rectangle (x + ar.X, y + ar.Y, ar.Width, ar.Height);
+ rects.Add (r);
+ }
+ allocations [w] = rects.ToArray ();
+ } else {
+ Gdk.Rectangle r = new Gdk.Rectangle (x + w.Allocation.X, y + w.Allocation.Y, w.Allocation.Width, w.Allocation.Height);
+ allocations [w] = new Gdk.Rectangle [] { r };
+ }
+ }
+ else {
+ allocations.Remove (w);
+ }
+ }
+
+ void HandleSwAreasChanged (object sender, EventArgs e)
+ {
+ UpdateAllocation ((Gtk.Widget)sender);
+ RedrawAll ();
+ }
+
+ void HandleWSizeAllocated (object o, SizeAllocatedArgs args)
+ {
+ UpdateAllocation ((Widget) o);
+ RedrawAll ();
+ }
+
+ void HandleWHidden (object sender, EventArgs e)
+ {
+ RedrawAll ();
+ }
+
+ void HandleWShown (object sender, EventArgs e)
+ {
+ RedrawAll ();
+ }
+
+ void HandleWDestroyed (object sender, EventArgs e)
+ {
+ Remove ((Widget)sender);
+ }
+
+ void RedrawAll ()
+ {
+ foreach (Widget w in widgets)
+ w.QueueDraw ();
+ }
+
+ public void DrawBackground (Gtk.Widget w)
+ {
+ DrawBackground (w, w.Allocation);
+ }
+
+ public void DrawBackground (Gtk.Widget w, Gdk.Rectangle allocation)
+ {
+ if (shadowSize == 0) {
+ Gdk.Rectangle wr = new Gdk.Rectangle (allocation.X, allocation.Y, allocation.Width, allocation.Height);
+ using (Cairo.Context ctx = Gdk.CairoHelper.Create (w.GdkWindow)) {
+ ctx.Rectangle (wr.X, wr.Y, wr.Width, wr.Height);
+ ctx.Color = GtkUtil.ToCairoColor (lightColor);
+ ctx.Fill ();
+ }
+ return;
+ }
+
+ List<Section> secsT = new List<Section> ();
+ List<Section> secsB = new List<Section> ();
+ List<Section> secsR = new List<Section> ();
+ List<Section> secsL = new List<Section> ();
+
+ int x, y;
+ w.GdkWindow.GetOrigin (out x, out y);
+ Gdk.Rectangle rect = new Gdk.Rectangle (x + allocation.X, y + allocation.Y, allocation.Width, allocation.Height);
+
+ Section s = new Section ();
+ s.Size = rect.Width;
+ secsT.Add (s);
+ secsB.Add (s);
+ s.Size = rect.Height;
+ secsL.Add (s);
+ secsR.Add (s);
+
+ foreach (var rects in allocations.Values) {
+ foreach (Gdk.Rectangle sr in rects) {
+ if (sr == rect)
+ continue;
+
+ if (sr.Right == rect.X)
+ RemoveSection (secsL, sr.Y - rect.Y, sr.Height);
+ if (sr.Bottom == rect.Y)
+ RemoveSection (secsT, sr.X - rect.X, sr.Width);
+ if (sr.X == rect.Right)
+ RemoveSection (secsR, sr.Y - rect.Y, sr.Height);
+ if (sr.Y == rect.Bottom)
+ RemoveSection (secsB, sr.X - rect.X, sr.Width);
+ }
+ }
+
+ Gdk.Rectangle r = new Gdk.Rectangle (allocation.X, allocation.Y, allocation.Width, allocation.Height);
+ using (Cairo.Context ctx = Gdk.CairoHelper.Create (w.GdkWindow)) {
+ ctx.Rectangle (r.X, r.Y, r.Width, r.Height);
+ ctx.Color = GtkUtil.ToCairoColor (lightColor);
+ ctx.Fill ();
+
+ DrawShadow (ctx, r, PositionType.Left, secsL);
+ DrawShadow (ctx, r, PositionType.Top, secsT);
+ DrawShadow (ctx, r, PositionType.Right, secsR);
+ DrawShadow (ctx, r, PositionType.Bottom, secsB);
+ }
+ }
+
+ void DrawShadow (Cairo.Context ctx, Gdk.Rectangle ar, PositionType pos, List<Section> secs)
+ {
+ foreach (Section s in secs) {
+ Cairo.Gradient pat = null;
+ Gdk.Rectangle r = ar;
+ switch (pos) {
+ case PositionType.Top:
+ r.Height = shadowSize > r.Height ? r.Height / 2 : shadowSize;
+ r.X += s.Offset;
+ r.Width = s.Size;
+ pat = new Cairo.LinearGradient (r.X, r.Y, r.X, r.Bottom);
+ break;
+ case PositionType.Bottom:
+ r.Y = r.Bottom - shadowSize;
+ r.Height = shadowSize > r.Height ? r.Height / 2 : shadowSize;
+ r.X = r.X + s.Offset;
+ r.Width = s.Size;
+ pat = new Cairo.LinearGradient (r.X, r.Bottom, r.X, r.Y);
+ break;
+ case PositionType.Left:
+ r.Width = shadowSize > r.Width ? r.Width / 2 : shadowSize;
+ r.Y += s.Offset;
+ r.Height = s.Size;
+ pat = new Cairo.LinearGradient (r.X, r.Y, r.Right, r.Y);
+ break;
+ case PositionType.Right:
+ r.X = r.Right - shadowSize;
+ r.Width = shadowSize > r.Width ? r.Width / 2 : shadowSize;
+ r.Y += s.Offset;
+ r.Height = s.Size;
+ pat = new Cairo.LinearGradient (r.Right, r.Y, r.X, r.Y);
+ break;
+ }
+ Cairo.Color c = GtkUtil.ToCairoColor (darkColor);
+ pat.AddColorStop (0, c);
+ c.A = 0;
+ pat.AddColorStop (1, c);
+ ctx.NewPath ();
+ ctx.Rectangle (r.X, r.Y, r.Width, r.Height);
+ ctx.Pattern = pat;
+ ctx.Fill ();
+ }
+ }
+
+ void RemoveSection (List<Section> secs, int offset, int size)
+ {
+ if (offset < 0) {
+ size += offset;
+ offset = 0;
+ }
+ if (size <= 0 || secs.Count == 0)
+ return;
+ Section last = secs [secs.Count - 1];
+ int rem = (last.Offset + last.Size) - (offset + size);
+ if (rem < 0) {
+ size += rem;
+ if (size <= 0)
+ return;
+ }
+ for (int n=0; n<secs.Count; n++) {
+ Section s = secs [n];
+ if (s.Offset >= offset + size)
+ continue;
+ if (offset >= s.Offset + s.Size)
+ continue;
+ if (offset <= s.Offset && offset + size >= s.Offset + s.Size) {
+ // Remove the whole section
+ secs.RemoveAt (n);
+ n--;
+ continue;
+ }
+ if (offset <= s.Offset) {
+ int newOfs = offset + size;
+ s.Size = s.Size - (newOfs - s.Offset);
+ s.Offset = newOfs;
+ secs [n] = s;
+ // Nothing else to remove
+ return;
+ }
+ if (offset + size >= s.Offset + s.Size) {
+ s.Size = offset - s.Offset;
+ secs [n] = s;
+ continue;
+ }
+ // Split section
+ Section s2 = new Section ();
+ s2.Offset = offset + size;
+ s2.Size = (s.Offset + s.Size) - (offset + size);
+ secs.Insert (n + 1, s2);
+ s.Size = offset - s.Offset;
+ secs [n] = s;
+ }
+ }
+ }
+
+ public interface IShadedWidget
+ {
+ IEnumerable<Gdk.Rectangle> GetShadedAreas ();
+ event EventHandler AreasChanged;
+ }
+}
+