5
using System.Collections.Generic;
7
namespace Mono.TextEditor.Theatrics
10
/// A scrolled window with the ability to put widgets beside the scrollbars.
12
public class SmartScrolledWindow : Bin
14
Adjustment vAdjustment;
15
Gtk.VScrollbar vScrollBar;
17
Adjustment hAdjustment;
18
Gtk.HScrollbar hScrollBar;
20
List<SmartScrolledWindowContainerChild> children = new List<SmartScrolledWindowContainerChild> ();
21
public enum ChildPosition {
28
public Adjustment Vadjustment {
29
get { return this.vAdjustment; }
32
public Adjustment Hadjustment {
33
get { return this.hAdjustment; }
36
public override ContainerChild this [Widget w] {
38
foreach (ContainerChild info in children.ToArray ()) {
46
public class SmartScrolledWindowContainerChild : Container.ContainerChild
48
public ChildPosition ChildPosition {
53
public SmartScrolledWindowContainerChild (Container parent, Widget child) : base (parent, child)
58
protected SmartScrolledWindow (IntPtr ptr) : base (ptr)
62
public SmartScrolledWindow ()
64
vAdjustment = new Adjustment (0, 0, 0, 0, 0, 0);
65
vAdjustment.Changed += HandleAdjustmentChanged;
67
vScrollBar = new VScrollbar (vAdjustment);
68
vScrollBar.Parent = this;
71
hAdjustment = new Adjustment (0, 0, 0, 0, 0, 0);
72
hAdjustment.Changed += HandleAdjustmentChanged;
74
hScrollBar = new HScrollbar (hAdjustment);
75
hScrollBar.Parent = this;
79
void HandleAdjustmentChanged (object sender, EventArgs e)
81
Adjustment adjustment = (Adjustment)sender;
82
Scrollbar scrollbar = adjustment == vAdjustment ? (Scrollbar)vScrollBar : hScrollBar;
83
bool newVisible = adjustment.Upper - adjustment.Lower > adjustment.PageSize;
84
if (scrollbar.Visible != newVisible) {
85
scrollbar.Visible = newVisible;
90
public override GLib.GType ChildType ()
92
return Gtk.Widget.GType;
95
protected override void ForAll (bool include_internals, Gtk.Callback callback)
97
base.ForAll (include_internals, callback);
99
if (include_internals) {
100
callback (vScrollBar);
101
callback (hScrollBar);
102
children.ForEach (child => callback (child.Child));
106
public void AddChild (Gtk.Widget child, ChildPosition position)
110
children.Add (new SmartScrolledWindowContainerChild (this, child) { ChildPosition = position });
113
protected override void OnAdded (Widget widget)
115
base.OnAdded (widget);
117
widget.SetScrollAdjustments (hAdjustment, vAdjustment);
120
protected override void OnRemoved (Widget widget)
123
foreach (var info in children.ToArray ()) {
124
if (info.Child == widget) {
125
children.Remove (info);
131
protected override void OnDestroyed ()
133
base.OnDestroyed (); // child gets destroyed here
134
vScrollBar.Destroy ();
135
hScrollBar.Destroy ();
136
vAdjustment.Destroy ();
137
hAdjustment.Destroy ();
140
protected override void OnSizeAllocated (Rectangle allocation)
142
base.OnSizeAllocated (allocation);
144
int vwidth = vScrollBar.Visible ? vScrollBar.Requisition.Width : 1;
145
int hheight = hScrollBar.Visible ? hScrollBar.Requisition.Height : 1;
146
Rectangle childRectangle = new Rectangle (allocation.X + 1, allocation.Y + 1, allocation.Width - vwidth, allocation.Height - hheight);
148
Child.SizeAllocate (childRectangle);
150
if (vScrollBar.Visible) {
151
int right = childRectangle.Right;
152
int vChildTopHeight = -1;
153
foreach (var child in children.Where (child => child.ChildPosition == ChildPosition.Top)) {
154
child.Child.SizeAllocate (new Rectangle (right, childRectangle.Y + vChildTopHeight, allocation.Width - vwidth, child.Child.Requisition.Height));
155
vChildTopHeight += child.Child.Requisition.Height;
157
int v = hScrollBar.Visible ? hScrollBar.Requisition.Height : 0;
158
vScrollBar.SizeAllocate (new Rectangle (right, childRectangle.Y + vChildTopHeight, vwidth, Allocation.Height - v - vChildTopHeight));
159
vScrollBar.Value = System.Math.Max (System.Math.Min (vAdjustment.Upper - vAdjustment.PageSize, vScrollBar.Value), vAdjustment.Lower);
162
if (hScrollBar.Visible) {
163
int v = vScrollBar.Visible ? vScrollBar.Requisition.Width : 0;
164
hScrollBar.SizeAllocate (new Rectangle (allocation.X, childRectangle.Bottom, Allocation.Width - v, hheight));
165
hScrollBar.Value = System.Math.Max (System.Math.Min (hAdjustment.Upper - hAdjustment.PageSize, hScrollBar.Value), hAdjustment.Lower);
169
static double GetWheelDelta (Scrollbar scrollbar, ScrollDirection direction)
171
double delta = System.Math.Pow (scrollbar.Adjustment.PageSize, 2.0 / 3.0);
172
if (direction == ScrollDirection.Up || direction == ScrollDirection.Left)
174
if (scrollbar.Inverted)
179
protected override bool OnScrollEvent (EventScroll evnt)
181
Scrollbar scrollWidget = (evnt.Direction == ScrollDirection.Up || evnt.Direction == ScrollDirection.Down) ? (Scrollbar)vScrollBar : hScrollBar;
183
if (scrollWidget.Visible) {
184
double newValue = scrollWidget.Adjustment.Value + GetWheelDelta (scrollWidget, evnt.Direction);
185
newValue = System.Math.Max (System.Math.Min (scrollWidget.Adjustment.Upper - scrollWidget.Adjustment.PageSize, newValue), scrollWidget.Adjustment.Lower);
186
scrollWidget.Adjustment.Value = newValue;
188
return base.OnScrollEvent (evnt);
191
protected override void OnSizeRequested (ref Gtk.Requisition requisition)
193
base.OnSizeRequested (ref requisition);
195
Child.SizeRequest ();
196
vScrollBar.SizeRequest ();
197
hScrollBar.SizeRequest ();
198
children.ForEach (child => child.Child.SizeRequest ());
201
protected override bool OnExposeEvent (EventExpose evnt)
203
Gdk.GC gc = Style.DarkGC (State);
204
evnt.Window.DrawLine (gc, Allocation.X, Allocation.Top, Allocation.X, Allocation.Bottom);
205
if (vScrollBar.Visible && hScrollBar.Visible) {
206
evnt.Window.DrawLine (gc, Allocation.Right, Allocation.Top, Allocation.Right, Allocation.Y + Allocation.Height / 2);
208
evnt.Window.DrawLine (gc, Allocation.Right, Allocation.Top, Allocation.Right, Allocation.Bottom);
210
evnt.Window.DrawLine (gc, Allocation.Left, Allocation.Y, Allocation.Right, Allocation.Y);
211
if (vScrollBar.Visible && hScrollBar.Visible) {
212
evnt.Window.DrawLine (gc, Allocation.Left, Allocation.Bottom, Allocation.Left + Allocation.Width / 2 , Allocation.Bottom);
214
evnt.Window.DrawLine (gc, Allocation.Left, Allocation.Bottom, Allocation.Right, Allocation.Bottom);
217
/* if (vScrollBar.Visible && hScrollBar.Visible) {
218
int vwidth = vScrollBar.Requisition.Width;
219
int hheight = hScrollBar.Requisition.Height;
221
evnt.Window.DrawRectangle (Style.BackgroundGC (State), true,
222
Allocation.Right - vwidth,
223
Allocation.Bottom - hheight,
226
return base.OnExposeEvent (evnt);