/*
 * EventGraph.h
 *
 * Copyright (C) 1999 Karim Yaghmour.
 *
 * This is distributed under GPL.
 *
 * Header for event graph engine.
 *
 * History : 
 *    K.Y., 28/06/99, Initial typing.
 */

#ifndef __TRACE_TOOLKIT_EVENT_GRAPH__
#define __TRACE_TOOLKIT_EVENT_GRAPH__

#include <EventDB.h>

#include <gtk/gtk.h>

#include "Pixmap.h"

#define EGRAPH_PIX_START           20
#define EGRAPH_USEC_PER_PIX       100      /* Number of micro-seconds to display per pixel */
#define EGRAPH_USEC_PER_PIX_MIN  0.01      /* Minimun number of micro-seconds to display per pixel */
#define EGRAPH_USEC_PER_PIX_MAX 10000      /* Maximum number of micro-seconds to display per pixel */
#define EGRAPH_ZOOM_IN_FACTOR       2      /* Factor by which number of usec/pix is divided */
#define EGRAPH_ZOOM_OUT_FACTOR      2      /* Factor by which number of usec/pix is multiplied */
#define EGRAPH_TEXT_TO_LINE_DIST    3      /* Distance between line and text */
#define EGRAPH_ICONS_WIDTH         16      /* The width of a system event icon */
#define EGRAPH_ICONS_HEIGHT        16      /* The height of a system event icon */
#define EGRAPH_ICONS_LABEL_LENGTH  47	   /* Length of displayed event icon text */
#define EGRAPH_ICON_CLEARANCE      64      /* Square of the hypotenuse length */
#define EGRAPH_ICON_FAR_ENOUGH      8      /* Half of EGRAPH_ICONS_WIDTH, no math */

/* Compare two of the PixAndMask structures for equality */
#define EGRAPH_PAM_EQUAL(a,b) (a.Pixmap == b.Pixmap && a.Mask == b.Mask)

/* Structure that fully defines a clipped pixmap */
typedef struct _pixAndMask
{
  GdkPixmap* Pixmap;    /* The pixmap itself */
  GdkBitmap* Mask;      /* The pixmap's clipping mask */
}pixAndMask;

/* ROC - Data structures to assist line and icon drawing deferral for
   speedier graphing.  Demo toolbar buttons exist in EventGraph.c
   to selectively use these features for comparison.  Use the runtime
   argument -Z to print out simple timing statistics.

   At zoom out many overdraws take place: icons and vertical lines on
   top of each other, or zero-length requests in horizontal lines.
   Avoiding those shows a speedup of x10 on a local display and x100
   over a network X connection.  One test trace went from 45000 line
   draw requests down to 800.

   For lines, provide a structure that holds the "best request" for
   a line.  For either horizontal or vertical lines, one of the four
   coordinates does not change so I only need to store 3 of them.
   Vertical: save the longest request in an X location.
   Horizontal: when switching from kernel to user (or vice verse)

   Icons: expanded (and renamed for clarity) the old "iconXY" structure which
   form the elements in the linked list EventIcons (formerly EventIconPos).
   Used during graph prep to first choose icons to minimize overdraws
   by using a simple collision detection with previously chosen icons.
   The icon lists built while drawing the lines, but the icons are
   drawn AFTERWARD so they're on top.  Finally the list is used 
   for traversal providing a target for a right-click.  Some of the data 
   is dynamic at draw-request time; allocate structures not just pointers. */
typedef struct _deferredLine
{
  guint  Same;                  /* Invariant coordinate */
  guint  Start;                 /* Start of coordinate variant */
  guint  End;                   /* End of coordinate variant */
  GdkGC* GC;			/* How to draw it */
} deferredLine;
typedef struct _eventInfo
{
  guint         x;               /* x coordinate of the associated event */
  guint         y;               /* y coordinate of the associated event */
  pixAndMask	EventIcon;       /* Event icon */
  event		Event;	         /* NOT a pointer, copy the data */
  gchar		EventText[EGRAPH_ICONS_LABEL_LENGTH + 1]; /* ditto */
} eventInfo;

/* The event graph widget */
typedef struct _eventGraph
{
  /* Widget state */
  gboolean      Init;             /* Is the event finished initializing */
  gboolean      ColorsAllocated;  /* Have the colors been allocated */
  gboolean      CreatedItemsGC;   /* Have the Items' Graphic contexts been created */
  gboolean      ShowHorizon;      /* Show horizon lines */
  gboolean      Benchmark;        /* Provide benchmarks */
  gboolean      FastIcons;        /* Draw icons fast */
  gboolean      FastHLines;       /* Draw horizontal lines fast */
  gboolean      FastVLines;       /* Draw vertical lines fast */

  /* The data */
  db*           EventDB;          /* The event database drawn */
  systemInfo*   System;           /* The system who's trace is drawn */
  gpointer      MainWindow;       /* The main window this event graph belongs to */
  process*      SelectedProc;     /* The currently selected process */

  /* Drawing benchmark data */
  gulong        NbUserIcons;      /* Number of user icons drawn */
  gulong        NbKernelIcons;    /* Number of kernel icons drawn */
  gulong        NbHLines;         /* Number of horizontal lines drawn */
  gulong        NbVLines;         /* Number of vertical lines drawn */

  /* The gtk  widgets */
  GtkWidget*    HPanned;          /* Horizontal panned widget */
  GtkWidget*    ProcVBox;         /* VBox to contain process stuff */
  GtkWidget*    DrawVBox;         /* VBox to contain drawing stuff */
  GtkWidget*    DummyBox;         /* This is to have the right spacing */

  GtkWidget*    ScrolledList;     /* Window containing scrollable list */
  GtkWidget*    List;             /* List of processes */

  GtkWidget*    HRuler;           /* Horizontal ruler */
  GtkWidget*    ScrolledDraw;     /* Window containing scrollable draw area */
  GtkWidget*    DrawArea;         /* Area where graph is drawn */
  GtkObject*    HAdjustment;      /* Horizontal adjustment */
  GtkWidget*    HScrollBar;       /* Scrollbar to scroll around the draw area */

  /* The gdk objects */
  GdkPixmap*    PixMap;           /* Pixmap where trace is drawn */
  GdkFont*      TextFont;         /* The text font used to draw text */
  GdkColor*     RedColor;         /* The colors themselves */
  GdkColor*     BlueColor; 
  GdkColor*     GreyColor;
  GdkColor*     GreenColor; 
  GdkColor*     BlackColor; 
  GdkColor*     WhiteColor;
  GdkColor*     OrangeColor;
  GdkColor*     YellowColor;
  GdkColor*     TurquoiseColor;
  GdkColor*     PurpleColor;

  /* The colors for each type of line */
  GdkGC*        BackgroundGC;     /* The background color */
  GdkGC*        HorizonGC;        /* Mark the horizontal horizon for every process to ease view */
  GdkGC*        ProcessGC;        /* Time in process */
  GdkGC*        Process0GC;       /* Time in process 0 */
  GdkGC*        KernelGC;         /* Time in kernel */
  GdkGC*        TaskGC;           /* Time in RTAI task */
  GdkGC*        RTAIGC;           /* Time in RTAI core */
  GdkGC*        SelectedGC;       /* Line drawn across the selected event */
  GdkGC*        SysCallGC;        /* Transition due to syscall entry or exit */
  GdkGC*        TrapGC;           /* Transition due to trap entry or exit */
  GdkGC*        InterruptGC;      /* Transition due to interrupt */
  GdkGC*        TextGC;           /* Text color */

  /* Drawing information */
  guint         NbProc;           /* Number of processes in trace */
  guint         NbTask;           /* Number of RTAI tasks in trace */
  guint         LabelHeight;      /* Height of the labels of the processes */
  guint         PixStart;         /* Number of pixels to put before first displayed event */
  guint         PixPerUSec;       /* Number of pixels per microsecond */
  gfloat        USecPerPix;       /* Number of microsecond per pixel */
  gulong        HTrueSize;        /* Horizontal true size */
  gulong        VTrueSize;        /* Vertical true size */
  guint         HDrawSize;        /* Horizontal draw size */
  guint         VDrawSize;        /* Vertical draw size */
  gdouble       StartTime;        /* Start time of trace */
  gdouble       Duration;         /* Duration of trace */
  gdouble       Interval;         /* Time interval drawable per scroll page */

  /* Overdraw reduction support for line/icon deferral and accumulation */
  gulong	NbIntervalEvents; /* Number of events in this Interval */
  deferredLine	VDef;		  /* For calculating vertical line deferrals */
  deferredLine	HDef;		  /*  "       "      horizontal "     "  */
  GSList*       EventIcons;       /* List of drawn events; was EventIconPos */

  /* Scroll information */
  event         DrawStartEvent;   /* First event to be drawn */
  event         DrawEndEvent;     /* Last event to be drawn */
  gdouble       DrawStartTime;    /* Time of first event to be drawn */
  gfloat        LastScrollVal;    /* Latest scroll position */

  /* Cached icons */
  pixAndMask    KernelTimer;      /* The "Kernel Timer" icon */
  pixAndMask    SysCall;          /* The "System Call" icon */
  pixAndMask    Trap;             /* The "Trap" icon*/
  pixAndMask    SchedChange;      /* The "Schedule change" icon */
  pixAndMask    BottomHalf;       /* The "Bottom Half" icon */
  pixAndMask    IOStart;          /* The "I/O Start" icon */
  pixAndMask    IOEnd;            /* The "I/O End" icon */
  pixAndMask    IRQ;              /* The "IRQ" icon */
} eventGraph;

/* Functions */
void        EGForceTraceRedraw
              (eventGraph*    /* The event graph who's redraw is to be forced */);
gboolean    EGMouseOnIcon
              (gint           /* The mouse's x coordinate */,
	       gint           /* The mouse's y coordinate */,
	       eventInfo*     /* The Icon to check for */);
void        EGZoomIn
              (eventGraph*    /* The event graph where we should zoom in */);
void        EGZoomOut
              (eventGraph*    /* The event graph where we should zoom out */);
void        EGZoomTimeFrame
              (eventGraph*    /* The event graph where to change the zoom */,
	       gdouble        /* The start of the time frame where to zoom */,
	       gdouble        /* The end of the time frame where to zoom */);
void        EGOneClickZoom
              (eventGraph*    /* The event graph where to change the zoom */,
               gdouble        /* The horizontal position where the click occured */,
	       gboolean       /* Zoom in (TRUE) or zoom out (FALSE) */);
void        EGScrollToEvent
              (eventGraph*    /* The event graph where we should adjust the position */,
	       event*         /* The event to scroll to */);
void        EGScrollLeft
              (eventGraph*    /* The event graph where we should adjust the position */);
void        EGScrollRight
              (eventGraph*    /* The event graph where we should adjust the position */);
void        EGScrollUp
              (eventGraph*    /* The event graph where we should adjust the position */);
void        EGScrollDown
              (eventGraph*    /* The event graph where we should adjust the position */);
void        EGPageUp
              (eventGraph*    /* The event graph where we should adjust the position */);
void        EGPageDown
              (eventGraph*    /* The event graph where we should adjust the position */);
void        EGSetHorizonView
              (eventGraph*    /* Event graph who's horizon is to be set */);
void        EGConnectSignals
              (eventGraph*    /* The event graph who's signals are to be connected */);
void        EGShowEventGraph
              (eventGraph*    /* The graph to display */);
eventGraph* EGCreateEventGraph
              (gpointer       /* Main window to which event graph belongs */);
void        EGDestroyEventGraph
              (eventGraph**   /* the event graph pointer's adress*/);
void        EGDisplayEventTrace
              (eventGraph*    /* The graph who's trace should be drawn */,
	       systemInfo*    /* System being drawn */,
	       db*            /* Database of events */);
void        EGClearEventGraph
              (eventGraph*    /* Event graph to be cleared */);
#endif /*  __TRACE_TOOLKIT_EVENT_GRAPH__ */
