In gui-gtk:
2005-02-06 Ben Maurer <bmaurer@ximian.com> * 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 <bmaurer@ximian.com> * 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
This commit is contained in:
Родитель
376f3a6154
Коммит
dd14ce1453
|
@ -1,3 +1,16 @@
|
|||
2005-02-06 Ben Maurer <bmaurer@ximian.com>
|
||||
|
||||
* 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 <bmaurer@ximian.com>
|
||||
|
||||
* Profile.cs, ProfileReader.cs: add stuff to get timeline
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 ++;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int StartTime {
|
||||
get { return start_t; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2005-02-06 Ben Maurer <bmaurer@ximian.com>
|
||||
|
||||
* 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 <bmaurer@ximian.com>
|
||||
|
||||
* TypeGraphViewer.cs: add the heap scroller in an ifdef
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче