From dd14ce1453709e3f9fa931335f9633854f222328 Mon Sep 17 00:00:00 2001 From: Ben Maurer Date: Sun, 6 Feb 2005 21:29:49 +0000 Subject: [PATCH] In gui-gtk: 2005-02-06 Ben Maurer * TypeGraphViewer.cs: Changes to use the real scroller. * HeapScroller.cs: A real scroller, based on the one in f-spot. In common: 2005-02-06 Ben Maurer * Profile.cs (MaxSize): new prop. (ContextDataTabulator): API change of ProfileReader (ContextDataTabulator.Checkpoint): missing a return here. * ProfileReader.cs: Don't do start file pos, but start file time. * TypeTabulator.cs: Add stuff to do a tabulation that starts midfile. Remove max size type stuff. * TypeGraphPlotter.cs: Get the max size from the profile svn path=/trunk/heap-prof/; revision=40224 --- src/viewer/common/ChangeLog | 13 + src/viewer/common/Profile.cs | 38 ++- src/viewer/common/ProfileReader.cs | 11 +- src/viewer/common/TypeGraphPlotter.cs | 14 +- src/viewer/common/TypeTabulator.cs | 46 ++- src/viewer/gui-gtk/ChangeLog | 6 + src/viewer/gui-gtk/HeapScroller.cs | 462 ++++++++++++++++++++++---- src/viewer/gui-gtk/TypeGraphViewer.cs | 82 +++-- 8 files changed, 551 insertions(+), 121 deletions(-) diff --git a/src/viewer/common/ChangeLog b/src/viewer/common/ChangeLog index 5cafdd8..a147134 100644 --- a/src/viewer/common/ChangeLog +++ b/src/viewer/common/ChangeLog @@ -1,3 +1,16 @@ +2005-02-06 Ben Maurer + + * Profile.cs (MaxSize): new prop. + (ContextDataTabulator): API change of ProfileReader + (ContextDataTabulator.Checkpoint): missing a return here. + + * ProfileReader.cs: Don't do start file pos, but start file time. + + * TypeTabulator.cs: Add stuff to do a tabulation that starts + midfile. Remove max size type stuff. + + * TypeGraphPlotter.cs: Get the max size from the profile + 2005-01-20 Ben Maurer * Profile.cs, ProfileReader.cs: add stuff to get timeline diff --git a/src/viewer/common/Profile.cs b/src/viewer/common/Profile.cs index f85de8a..69795a0 100644 --- a/src/viewer/common/Profile.cs +++ b/src/viewer/common/Profile.cs @@ -21,33 +21,26 @@ public class Profile { public int [] GetContextObjsForTime (int max_t) { - int ev = Metadata.GetTimelineBefore (EventType.Checkpoint, max_t); - ContextDataTabulator tab; - - if (ev != -1) - tab = new ContextDataTabulator (this, Metadata.GetTimeline (ev).FilePos, max_t); - else - tab = new ContextDataTabulator (this, 0, max_t); - + ContextDataTabulator tab = new ContextDataTabulator (this, max_t); tab.Read (); - return tab.ContextData; } class ContextDataTabulator : ProfileReader { public int [] ContextData; - public ContextDataTabulator (Profile p, long s, int e) : base (p, s, e) + public ContextDataTabulator (Profile p, int s) : base (p, s, s) { - if (s == 0) + if (p.Metadata.GetTimelineBefore (EventType.Checkpoint, s) == -1) ContextData = new int [ContextTableSize]; } protected override void Checkpoint (int time, int event_num) { - if (ContextData != null) + if (ContextData != null) { base.Checkpoint (time, event_num); - + return; + } int [] dummy; ReadCheckpoint (out dummy, out ContextData); @@ -100,4 +93,21 @@ public class Profile { public Timeline [] Timeline { get { return Metadata.Timeline; } } -} \ No newline at end of file + + int max_size = -1; + public int MaxSize { + get { + + if (max_size != -1) + return max_size; + + Timeline [] tl = Timeline; + + for (int i = tl.Length - 1; i >= 0; i --) + if (tl [i].Event == EventType.HeapResize) + return max_size = tl [i].SizeHigh; + + return max_size = 0; + } + } +} diff --git a/src/viewer/common/ProfileReader.cs b/src/viewer/common/ProfileReader.cs index 9ac26ae..637c6a0 100644 --- a/src/viewer/common/ProfileReader.cs +++ b/src/viewer/common/ProfileReader.cs @@ -13,9 +13,16 @@ public abstract class ProfileReader { Profile = p; } - public ProfileReader (Profile p, long startpos, int end_t) + public ProfileReader (Profile p, int start_t, int end_t) { - this.startpos = startpos; + + int ev = p.Metadata.GetTimelineBefore (EventType.Checkpoint, start_t); + + if (ev != -1) + startpos = p.Metadata.GetTimeline (ev).FilePos; + else + startpos = 0; + this.end_t = end_t; Profile = p; } diff --git a/src/viewer/common/TypeGraphPlotter.cs b/src/viewer/common/TypeGraphPlotter.cs index cb01e72..c05a586 100644 --- a/src/viewer/common/TypeGraphPlotter.cs +++ b/src/viewer/common/TypeGraphPlotter.cs @@ -16,6 +16,7 @@ class Plotter { int xsize, ysize; TypeTabulator d; TypeList tl; + Profile Profile; public Plotter (int xsize, int ysize, TypeTabulator d, TypeList tl) { @@ -23,6 +24,7 @@ class Plotter { this.ysize = ysize; this.d = d; this.tl = tl; + this.Profile = d.Profile; FixupData (); } @@ -33,10 +35,12 @@ class Plotter { void FixupData () { - end_t = ((TimeData) d.Data [d.Data.Count - 1]).Time; + int start_t = d.StartTime; + int end_t = ((TimeData) d.Data [d.Data.Count - 1]).Time; + int del_t = end_t - start_t; data = new ArrayList (); - int size_threshold = d.MaxSize / ysize; + int size_threshold = Profile.MaxSize / ysize; foreach (TimeData td in d.Data) { if (td.HeapSize < size_threshold) @@ -48,7 +52,7 @@ class Plotter { p.Data = td; p.Time = td.Time; - p.X = td.Time * xsize / end_t; + p.X = (td.Time - start_t) * xsize / del_t; p.OtherSize = td.OtherSize; p.TypeData = new int [tl.TypeIndexes.Length]; p.HeapSize = td.HeapSize; @@ -92,7 +96,7 @@ class Plotter { psize = tp.TypeData [i]; line [j].X = tp.X; - line [j].Y = ysize - checked (offsets [j] + (int)((long)psize * (long) ysize / (long)d.MaxSize)); + line [j].Y = ysize - checked (offsets [j] + (int)((long)psize * (long) ysize / (long)Profile.MaxSize)); offsets [j] = ysize - line [j].Y; j ++; } @@ -124,7 +128,7 @@ class Plotter { int psize = tp.HeapSize; line [j].X = tp.X; - line [j].Y = ysize - checked ((int)((long)psize * (long) ysize / (long)d.MaxSize)); + line [j].Y = ysize - checked ((int)((long)psize * (long) ysize / (long)Profile.MaxSize)); j ++; } diff --git a/src/viewer/common/TypeTabulator.cs b/src/viewer/common/TypeTabulator.cs index 112517a..55d63d4 100644 --- a/src/viewer/common/TypeTabulator.cs +++ b/src/viewer/common/TypeTabulator.cs @@ -15,23 +15,47 @@ class TypeTabulator : ProfileReader { const int DeltaT = 50; const double Threshold = .005; - - public ArrayList Data; - public int MaxSize; + public ArrayList Data = new ArrayList (); public long [] TotalTypeSizes; public bool [] IsSizeLongEnough; int [] current_type_data; - int [] current_context_data; int last_time; int cur_heap_size; + int start_t, end_t; public TypeTabulator (Profile p) : base (p) { - Data = new ArrayList (); current_type_data = new int [TypeTableSize]; } + public TypeTabulator (Profile p, int start_t, int end_t) : base (p, start_t, end_t) + { + this.start_t = start_t; + this.end_t = end_t; + if (p.Metadata.GetTimelineBefore (EventType.Checkpoint, start_t) == -1) + current_type_data = new int [TypeTableSize]; + } + + protected override void Checkpoint (int time, int event_num) + { + if (current_type_data != null) { + base.Checkpoint (time, event_num); + return; + } + + int [] dummy; + + int last_resize = Profile.Metadata.GetTimelineBefore (EventType.HeapResize, time); + + if (last_resize != -1) { + cur_heap_size = Profile.Metadata.GetTimeline (last_resize).SizeHigh; + } + + ReadCheckpoint (out current_type_data, out dummy); + Split (time); + } + void Split (int time) { TimeData td = new TimeData (); @@ -42,8 +66,6 @@ class TypeTabulator : ProfileReader { foreach (int i in td.TypeData) td.TotalSize += i; - MaxSize = Math.Max (td.HeapSize, MaxSize); - Data.Add (td); } @@ -124,7 +146,9 @@ class TypeTabulator : ProfileReader { public void Process () { - int cutoff = (int) (MaxSize * Threshold); + + Split (end_t); + int cutoff = (int) (Profile.MaxSize * Threshold); TotalTypeSizes = new long [TypeTableSize]; IsSizeLongEnough = new bool [TypeTableSize]; @@ -147,4 +171,8 @@ class TypeTabulator : ProfileReader { } } } -} \ No newline at end of file + + public int StartTime { + get { return start_t; } + } +} diff --git a/src/viewer/gui-gtk/ChangeLog b/src/viewer/gui-gtk/ChangeLog index 5c9cd9d..eaa1bc6 100644 --- a/src/viewer/gui-gtk/ChangeLog +++ b/src/viewer/gui-gtk/ChangeLog @@ -1,3 +1,9 @@ +2005-02-06 Ben Maurer + + * TypeGraphViewer.cs: Changes to use the real scroller. + + * HeapScroller.cs: A real scroller, based on the one in f-spot. + 2005-01-20 Ben Maurer * TypeGraphViewer.cs: add the heap scroller in an ifdef diff --git a/src/viewer/gui-gtk/HeapScroller.cs b/src/viewer/gui-gtk/HeapScroller.cs index 40cd4ee..5d4346c 100644 --- a/src/viewer/gui-gtk/HeapScroller.cs +++ b/src/viewer/gui-gtk/HeapScroller.cs @@ -6,90 +6,410 @@ using Gtk; using System.Reflection; using System.Runtime.InteropServices; -// -// A sample using inheritance to draw -// -class HeapScroller : DrawingArea { +// because some people are too fucking scared of something not in ECMA +using GRect = Gdk.Rectangle; - Profile p; +public class HeapScroller : Bin { + int border = 8; + int box_spacing = 2; + int box_top_padding = 6; + private Glass glass; + + Gdk.Window event_window; + + public GRect background; + public GRect legend; - Gdk.Pixmap bitmap_cache; - - Gdk.Rectangle current_allocation; // The current allocation. - bool allocated = false; - - public HeapScroller (Profile p) + static bool BoxTest (GRect bounds, double x, double y) { - this.p = p; - Events |= Gdk.EventMask.ButtonPressMask; - - SetSizeRequest (100, 100); + if (x >= bounds.X && + x < bounds.X + bounds.Width && + y >= bounds.Y && + y < bounds.Y + bounds.Height) + return true; + + return false; } - + + protected override bool OnButtonPressEvent (Gdk.EventButton args) + { + double x = args.X + Allocation.X; + double y = args.Y + Allocation.Y; + + if (glass.IsInside (x, y)) + glass.StartDrag (x, y, args.Time); + else { + int x_new = (int) x - background.X; + + if (x_new < 0) + x_new = 0; + else if (x_new + glass.Width > background.Width) + x_new = background.Width - glass.Width; + + glass.Position = x_new; + + ScrollChanged (); + } + + return base.OnButtonPressEvent (args); + } + + protected override bool OnButtonReleaseEvent (Gdk.EventButton args) + { + double x = args.X + Allocation.X; + double y = args.Y + Allocation.Y; + + if (glass.Dragging) + glass.EndDrag (x, y); + + return base.OnButtonReleaseEvent (args); + } + + protected override bool OnMotionNotifyEvent (Gdk.EventMotion args) + { + double x = args.X + Allocation.X; + double y = args.Y + Allocation.Y; + + + GRect box = glass.Bounds (); + + if (glass.Dragging) { + glass.UpdateDrag (x, y); + + } else { + if (glass.IsInside (x, y)) + glass.State = StateType.Prelight; + else + glass.State = StateType.Normal; + } + + return base.OnMotionNotifyEvent (args); + } + + protected override void OnRealized () + { + Flags |= (int)WidgetFlags.Realized; + GdkWindow = ParentWindow; + + base.OnRealized (); + + Gdk.WindowAttr attr = Gdk.WindowAttr.Zero; + attr.WindowType = Gdk.WindowType.Child; + + attr.X = Allocation.X; + attr.Y = Allocation.Y; + attr.Width = Allocation.Width; + attr.Height = Allocation.Height; + attr.Wclass = Gdk.WindowClass.InputOnly; + attr.EventMask = (int) Events; + attr.EventMask |= (int) (Gdk.EventMask.ButtonPressMask | + Gdk.EventMask.ButtonReleaseMask | + Gdk.EventMask.PointerMotionMask); + + event_window = new Gdk.Window (GdkWindow, attr, (int) (Gdk.WindowAttributesType.X | Gdk.WindowAttributesType.Y)); + event_window.UserData = this.Handle; + } + + protected override void OnUnrealized () + { + event_window.Dispose (); + event_window = null; + } + + protected void ScrollChanged () + { + if (OnScrolled != null) + OnScrolled (); + } + + public abstract class Manipulator { + protected HeapScroller selector; + public bool Dragging; + + int x_0; + int x_n; + + public abstract int Width { + get; + } + + + public void StartDrag (double x, double y, uint time) + { + State = StateType.Active; + Dragging = true; + x_n = Position; + x_0 = (int)x; + + Console.WriteLine ("Position: {0}", Position); + } + + public void UpdateDrag (double x, double y) + { + + GRect then = Bounds (); + + int x_new = position + (int) x - x_0; + + if (x_new < 0) + x_n = 0; + else if (x_new + Width > selector.background.Width) + x_n = selector.background.Width - Width; + else + x_n = x_new; + + GRect now = Bounds (); + + if (selector.Visible) { + selector.GdkWindow.InvalidateRect (then, false); + selector.GdkWindow.InvalidateRect (now, false); + } + } + + public void EndDrag (double x, double y) + { + GRect box = Bounds (); + + Position = x_n; + State = StateType.Prelight; + + Dragging = false; + + selector.ScrollChanged (); + + Console.WriteLine ("Position: {0}", Position); + } + + private StateType state; + public StateType State { + get { + return state; + } + set { + if (state != value) { + selector.GdkWindow.InvalidateRect (Bounds (), false); + } + state = value; + } + } + + private int position; + public int Position { + get { + return position; + } + set { + GRect then = Bounds (); + position = value; + GRect now = Bounds (); + + if (selector.Visible) { + selector.GdkWindow.InvalidateRect (then, false); + selector.GdkWindow.InvalidateRect (now, false); + } + + + } + } + + public abstract void Draw (GRect area); + public abstract GRect Bounds (); + + public virtual bool IsInside (double x, double y) + { + return BoxTest (Bounds (), x, y); + } + + public Manipulator (HeapScroller selector) + { + this.selector = selector; + } + + protected int XPos { + get { + if (! Dragging) + return Position; + + return x_n; + } + } + } + + private class Glass : Manipulator { + private int handle_height = 15; + + private int border { + get { + return selector.box_spacing * 2; + } + } + + private GRect InnerBounds () + { + GRect box = GRect.Zero; + box.Height = selector.background.Height; + box.Y = selector.background.Y; + + box.X = selector.background.X + XPos; + box.Width = Width; + + return box; + } + + public override GRect Bounds () + { + GRect box = InnerBounds (); + + box.X -= border; + box.Y -= border; + box.Width += 2 * border; + box.Height += 2 * border + handle_height; + + return box; + } + + public override void Draw (GRect area) + { + GRect inner = InnerBounds (); + GRect bounds = Bounds (); + + if (bounds.Intersect (area, out area)) { + + + int i = 0; + GRect box = inner; + box.Width -= 1; + box.Height -= 1; + while (i < border) { + box.X -= 1; + box.Y -= 1; + box.Width += 2; + box.Height += 2; + + selector.GdkWindow.DrawRectangle (selector.Style.BackgroundGC (State), + false, box); + i++; + } + + Style.PaintHandle (selector.Style, selector.GdkWindow, State, ShadowType.None, + area, selector, "glass", bounds.X, inner.Y + inner. Height, + bounds.Width, handle_height + border, Orientation.Horizontal); + + Style.PaintShadow (selector.Style, selector.GdkWindow, State, ShadowType.Out, + area, selector, null, bounds.X, bounds.Y, bounds.Width, bounds.Height); + + Style.PaintShadow (selector.Style, selector.GdkWindow, State, ShadowType.In, + area, selector, null, inner.X, inner.Y, inner.Width, inner.Height); + + } + } + + public override int Width { + get { return (selector.TimeSpan * selector.background.Width) / selector.maxt; } + } + + public Glass (HeapScroller selector) : base (selector) {} + } + + protected override void OnMapped () + { + base.OnMapped (); + if (event_window != null) + event_window.Show (); + } + protected override bool OnExposeEvent (Gdk.EventExpose args) { - if (bitmap_cache == null) { - bitmap_cache = new Gdk.Pixmap (GdkWindow, current_allocation.Width, current_allocation.Height, -1); + bitmap_cache = new Gdk.Pixmap (GdkWindow, background.Width, background.Height, -1); bitmap_cache.DrawRectangle (Style.WhiteGC, true, 0, 0, - current_allocation.Width, current_allocation.Height); + background.Width, background.Height); using (Graphics g = Gtk.DotNet.Graphics.FromDrawable (bitmap_cache)) { Plot (g); } } - Gdk.Rectangle area = args.Area; + + Gdk.Rectangle area; + if (args.Area.Intersect (background, out area)) { + GRect active = background; + + if (active.Intersect (area, out active)) { + GdkWindow.DrawRectangle (Style.BaseGC (State), true, active); + } + } + GdkWindow.DrawDrawable (Style.BlackGC, bitmap_cache, - area.X, area.Y, - area.X, area.Y, - area.Width, area.Height); - - return true; + 0, 0, + background.X, background.Y, + background.Width, background.Height); + + Style.PaintShadow (this.Style, GdkWindow, State, ShadowType.In, area, + this, null, background.X, background.Y, + background.Width, background.Height); + + if (glass != null) { + glass.Draw (args.Area); + } + + return base.OnExposeEvent (args); } - protected override void OnSizeAllocated (Gdk.Rectangle allocation) + protected override void OnSizeAllocated (GRect alloc) { - allocated = true; - current_allocation = allocation; + base.OnSizeAllocated (alloc); + int legend_height = 20; + + background = new GRect (alloc.X + border, alloc.Y + border, + alloc.Width - 2* border, + alloc.Height - 2 * border - legend_height); + + legend = new GRect (border, background.Y + background.Height, + background.Width, legend_height); + + if (event_window != null) { + event_window.MoveResize (alloc.X, alloc.Y, alloc.Width, alloc.Height); + event_window.Move (alloc.X, alloc.Y); + } + UpdateCache (); - base.OnSizeAllocated (allocation); + + Console.WriteLine ("Background {0}", background); } - void UpdateCache () + public HeapScroller (Profile p) { - if (bitmap_cache != null) - bitmap_cache.Dispose (); - - bitmap_cache = null; - } - - protected override bool OnButtonPressEvent (Gdk.EventButton e) - { - if (e.Button != 3) - return false; - - Console.WriteLine ("Button press at ({0}, {1})", e.X, e.Y); - - return true; - } - - - void Plot (Graphics g) - { - int maxx = current_allocation.Width; - int maxy = current_allocation.Height; - + this.p = p; + Events |= Gdk.EventMask.ButtonPressMask; Timeline [] tl = p.Timeline; - int maxt = tl [tl.Length - 1].Time; - int maxsz = 0; + maxt = tl [tl.Length - 1].Time; - foreach (Timeline t in tl) - if (t.Event == EventType.HeapResize) - maxsz = t.SizeHigh; + time_span = maxt / 5; + + SetSizeRequest (100, 100); + + Flags |= (int)WidgetFlags.NoWindow; + + background = GRect.Zero; + glass = new Glass (this); + } + + Profile p; + + Gdk.Pixmap bitmap_cache; + + void Plot (Graphics g) + { + int maxx = background.Width; + int maxy = background.Height; + + Timeline [] tl = p.Timeline; + + int maxsz = p.MaxSize; int lastx = 0; @@ -127,4 +447,30 @@ class HeapScroller : DrawingArea { lasty = ly; } } -} + + int maxt; + int time_span; + + public int StartTime { + get { return (glass.Position * maxt) / background.Width; } + } + + public int EndTime { + get { return StartTime + time_span; } + } + + public int TimeSpan { + get { return time_span; } + } + + void UpdateCache () + { + if (bitmap_cache != null) + bitmap_cache.Dispose (); + + bitmap_cache = null; + } + + public delegate void ScrollChangedDelegate (); + public event ScrollChangedDelegate OnScrolled; +} \ No newline at end of file diff --git a/src/viewer/gui-gtk/TypeGraphViewer.cs b/src/viewer/gui-gtk/TypeGraphViewer.cs index a7082ba..c355730 100644 --- a/src/viewer/gui-gtk/TypeGraphViewer.cs +++ b/src/viewer/gui-gtk/TypeGraphViewer.cs @@ -7,35 +7,40 @@ using System.Reflection; using System.Runtime.InteropServices; class TypeGraphComponent : ShellComponent { - DrawingArea d; + TypeGrpah d; TypeTabulator t; TypeList tl; HPaned paned; VBox box; HeapScroller scroller; + public Profile Profile; public TypeGraphComponent (Profile p) { - - t = new TypeTabulator (p); - t.Read (); - t.Process (); + Profile = p; Title = "Type Graph"; - this.t = t; - tl = new TypeList (t); - box = new VBox (); box.Spacing = 12; - - paned = new HPaned (); - d = new PrettyGraphic (t, tl, this); - + + Add (box); + + scroller = new HeapScroller (p); + scroller.OnScrolled += delegate { t = null; d.UpdateCache (); d.QueueDraw (); }; + box.PackStart (scroller, false, false, 0); + + // FIXME: HACKISH + TypeTabulator xxx = new TypeTabulator (p); + xxx.Read (); + xxx.Process (); + tl = new TypeList (xxx); + + d = new TypeGrpah (tl, this); ScrolledWindow sw = new ScrolledWindow (); sw.Add (new TypeListNodeStore (tl).GetNodeView ()); @@ -43,16 +48,30 @@ class TypeGraphComponent : ShellComponent { paned.Pack1 (d, true, true); paned.Pack2 (sw, false, true); - Add (box); - -#if false - scroller = new HeapScroller (p); - - box.PackStart (scroller, false, false, 0); -#endif - box.PackStart (paned, true, true, 0); } + + public int StartTime { + get { return scroller.StartTime; } + } + + public int EndTime { + get { return scroller.EndTime; } + } + + public TypeTabulator CurrentTabulator { + get { + if (t == null) { + Console.WriteLine ("start: {0}", StartTime); + Console.WriteLine ("end: {0}", EndTime); + t = new TypeTabulator (Profile, StartTime, EndTime); + t.Read (); + t.Process (); + } + + return t; + } + } } @@ -170,23 +189,20 @@ class TypeListTreeNode : TreeNode { // // A sample using inheritance to draw // -class PrettyGraphic : DrawingArea { - - TypeTabulator t; +class TypeGrpah : DrawingArea { TypeList tl; Gdk.Pixmap bitmap_cache; //System.Drawing.Bitmap bitmap_cache; - Gdk.Rectangle current_allocation; // The current allocation. + Gdk.Rectangle allocation; // The current allocation. bool allocated = false; Plotter plot; TypeGraphComponent parent; - public PrettyGraphic (TypeTabulator t, TypeList tl, TypeGraphComponent parent) + public TypeGrpah (TypeList tl, TypeGraphComponent parent) { Events |= Gdk.EventMask.ButtonPressMask; - - this.t = t; + this.tl = tl; this.parent = parent; SetSizeRequest (700, 700); @@ -196,12 +212,12 @@ class PrettyGraphic : DrawingArea { { if (bitmap_cache == null) { - bitmap_cache = new Gdk.Pixmap (GdkWindow, current_allocation.Width, current_allocation.Height, -1); + bitmap_cache = new Gdk.Pixmap (GdkWindow, allocation.Width, allocation.Height, -1); bitmap_cache.DrawRectangle (Style.WhiteGC, true, 0, 0, - current_allocation.Width, current_allocation.Height); + allocation.Width, allocation.Height); using (Graphics g = Gtk.DotNet.Graphics.FromDrawable (bitmap_cache)) { - plot = new Plotter (current_allocation.Width, current_allocation.Height, t, tl); + plot = new Plotter (allocation.Width, allocation.Height, parent.CurrentTabulator, tl); plot.Draw (g); } } @@ -219,12 +235,12 @@ class PrettyGraphic : DrawingArea { protected override void OnSizeAllocated (Gdk.Rectangle allocation) { allocated = true; - current_allocation = allocation; + this.allocation = allocation; UpdateCache (); base.OnSizeAllocated (allocation); } - void UpdateCache () + public void UpdateCache () { if (bitmap_cache != null) bitmap_cache.Dispose (); @@ -243,7 +259,7 @@ class PrettyGraphic : DrawingArea { if (tp.X >= e.X) { Console.WriteLine ("Found {0}", tp.Time); - parent.Parent.Add (new BacktraceViewerComponent (tp.Data, t.Profile)); + parent.Parent.Add (new BacktraceViewerComponent (tp.Data, parent.Profile)); break; }