aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/Interface.cs
diff options
context:
space:
mode:
authorjpbruyere <jp_bruyere@hotmail.com>2013-11-16 09:16:43 +0100
committerjpbruyere <jp_bruyere@hotmail.com>2013-11-16 09:16:43 +0100
commitdab0f2befeda33bd1c8e59ec41a2e1768712086b (patch)
treee1dc606a3d8eeccd221e8adc03edc8639c3daa17 /src/Interface.cs
first commit
Diffstat (limited to 'src/Interface.cs')
-rw-r--r--src/Interface.cs567
1 files changed, 567 insertions, 0 deletions
diff --git a/src/Interface.cs b/src/Interface.cs
new file mode 100644
index 00000000..1abef72d
--- /dev/null
+++ b/src/Interface.cs
@@ -0,0 +1,567 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using OpenTK.Graphics.OpenGL;
+
+using GLU = OpenTK.Graphics.Glu;
+using OpenTK.Input;
+using OpenTK;
+using Cairo;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace go
+{
+ public delegate void WidgetEvent (GraphicObject sender);
+
+ public delegate void ButtonWidgetClick (Button sender);
+ //public delegate object ValueGetter(Widget sender);
+
+
+ public static class Interface
+ {
+
+ [DllImport ("libgo.so")]
+ private static extern void TTY_init ();
+
+ [DllImport ("libgo.so")]
+ private static extern void TTY_attend ();
+
+ [DllImport ("libgo.so")]
+ private static extern void FB_init (out Framebuffer fb);
+
+ [DllImport ("libgo.so")]
+ public static extern void DEV_init (int largeur, int hauteur);
+
+ [DllImport ("libgo.so")]
+ public static extern void DEV_lectureEvenement (out Evenement e);
+
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public struct Framebuffer
+ {
+ public IntPtr ptr;
+ public int hauteur;
+ public int largeur;
+ public int linelength;
+ }
+
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public struct Evenement
+ {
+ public int type;
+ public int data1;
+ public int data2;
+ public int data3;
+ public IntPtr emetteur;
+ public const int MOUSE_DOWN = 0x21;
+ public const int MOUSE_UP = 0x22;
+ public const int MOUSE_MVT = 0x23;
+ }
+
+ public static List<Panel> panels = new List<Panel> ();
+ public static Panel activePanel;
+
+ #region cairo contexte
+ public static Context ctx;
+ public static Surface surf;
+ public static byte[] buffer; //opengl byte buffer for rastering
+
+ public static Surface mouseGraphic;
+
+ public static void createFrameBufferSurface ()
+ {
+
+
+ Framebuffer fb;
+ FB_init (out fb);
+ surf = new Cairo.ImageSurface (fb.ptr, Format.ARGB32, fb.largeur, fb.hauteur, fb.linelength);
+ ctx = new Context (surf);
+
+ DEV_init (fb.largeur, fb.hauteur);
+ TTY_init();
+
+ initMouseGraphic ();
+
+ }
+
+ public static void createWin32Surface ()
+ {
+ IntPtr hdc = Win32.GetDC (IntPtr.Zero);
+ surf = new Win32Surface (hdc);
+ ctx = new Context (surf);
+ }
+ public static void createOpenGLSurface()
+ {
+ int stride = 4 * renderBounds.Width;
+
+ int bmpSize = Math.Abs(stride) * renderBounds.Height;
+ buffer = new byte[bmpSize];
+ surf = new ImageSurface(buffer, Format.Argb32, renderBounds.Width, renderBounds.Height, stride);
+ ctx = new Context(surf);
+ }
+ public static void createOpenGLSurface (Rectangle bounds)
+ {
+ renderBounds = bounds;
+
+ createOpenGLSurface();
+ }
+
+ public static void initMouseGraphic ()
+ {
+ mouseGraphic = new ImageSurface (@"Pointeurs/left_ptr.png");
+ //mouseGraphic = new ImageSurface(@"test.png");
+ Thread t = new Thread (deviceThread);
+ t.Start ();
+ }
+
+ public static void deviceThread ()
+ {
+ while (true)
+ {
+ TTY_attend();
+
+ Interface.Evenement e;
+ Interface.DEV_lectureEvenement (out e);
+
+ switch (e.type) {
+ case Evenement.MOUSE_MVT:
+ //erase previouse mouse
+// ctx.Operator = Operator.Clear;
+// ctx.SetSourceSurface(mouseGraphic,mouseX,mouseY);
+// ctx.Paint();
+// ctx.Operator = Operator.Over;
+ lock(redrawClip)
+ {
+ redrawClip.AddRectangle (new Rectangle (mouseX, mouseY, 48, 48));
+ }
+ mouseX = e.data1;
+ mouseY = e.data2;
+
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ #endregion
+
+ //for panel only
+ public static Rectangles redrawClip = new Rectangles ();
+ public static char decimalSeparator = '.';
+
+ #region Mouse Handling"
+ public static bool MouseIsInInterface = false;
+ //used only for pannel mouse grabbing, should extend it to other go
+ public static bool grabMouse = false;
+ public static MouseDevice Mouse;
+
+ public static bool ProcessMousePosition (Point mousePos, Vector2 Delta)
+ {
+ if (checkMouse (mousePos)) {
+ if (Delta != Vector2.Zero) {
+ if (Interface.activePanel != null) {
+ Interface.activePanel.updateMouseCursor ();
+ }
+
+
+ if (Mouse [MouseButton.Left]) {
+ if (Interface.activePanel != null) {
+ if (Interface.grabMouse) {
+ go.Panel p = Interface.activePanel;
+ p.registerForRedraw (); //add previous clip rect
+ switch (Interface.activePanel.mouseBorderPosition) {
+ case PanelBorderPosition.Top:
+ p.y -= (int)Delta.Y;
+ p.height += (int)Delta.Y;
+ break;
+ case PanelBorderPosition.Left:
+ p.x -= (int)Delta.X;
+ p.width += (int)Delta.X;
+ break;
+ case PanelBorderPosition.Right:
+ p.width -= (int)Delta.X;
+ break;
+ case PanelBorderPosition.Bottom:
+ p.height -= (int)Delta.Y;
+ break;
+ case PanelBorderPosition.TopLeft:
+ p.y -= (int)Delta.Y;
+ p.height += (int)Delta.Y;
+ p.x -= (int)Delta.X;
+ p.width += (int)Delta.X;
+ break;
+ case PanelBorderPosition.TopRight:
+ p.y -= (int)Delta.Y;
+ p.height += (int)Delta.Y;
+ p.width -= (int)Delta.X;
+ break;
+ case PanelBorderPosition.BottomLeft:
+ p.height -= (int)Delta.Y;
+ p.x -= (int)Delta.X;
+ p.width += (int)Delta.X;
+ break;
+ case PanelBorderPosition.BottomRight:
+ p.height -= (int)Delta.Y;
+ p.width -= (int)Delta.X;
+ break;
+ case PanelBorderPosition.Moving:
+ p.x -= (int)Delta.X;
+ p.y -= (int)Delta.Y;
+ p.updatePosition ();
+ break;
+ case PanelBorderPosition.ClientArea:
+ break;
+ default:
+ break;
+ }
+ p.invalidateLayout ();
+ }
+ }
+ }
+ }
+ return true;
+ } else
+ return false;
+ }
+
+ public static void ProcessMouseWheel (int delta)
+ {
+ int step = 15;
+ if (activePanel != null)
+ activePanel.ProcessMouseWeel (delta * step);
+ }
+
+ static bool checkMouse (Point mousePos)
+ {
+ if (grabMouse)
+ return true;
+ else if (activePanel != null) {
+ if (activePanel.ProcessMousePosition (mousePos))
+ return true;
+ else
+ activePanel = null;
+ }
+
+ foreach (Panel p in panels) {
+ if (p.isVisible) {
+ if (p.ProcessMousePosition (mousePos)) {
+ activePanel = p;
+ activePanel.putOnTop ();
+ Interface.MouseIsInInterface = true;
+ return true;
+ }
+ }
+ }
+ activePanel = null;
+
+ Interface.MouseIsInInterface = false;
+ return false;
+ }
+
+ public static void Mouse_ButtonDown (object sender, MouseButtonEventArgs e)
+ {
+ if (!MouseIsInInterface)
+ return;
+
+ Point m = e.Position;
+
+ if (activePanel != null) {
+ activePanel.putOnTop ();
+
+ Rectangle r = Interface.activePanel.ScreenCoordClientBounds;
+
+ if (r.Contains (m)) {
+ grabMouse = false;
+ } else {
+ grabMouse = true;
+ }
+ activePanel.ProcessMouseDown (e.Position);
+ activePanel.updateMouseCursor ();
+ }
+
+ if (hoverWidget != null)
+ hoverWidget.ProcessMouseDown (e.Position);
+ }
+
+ public static void Mouse_ButtonUp (object sender, MouseButtonEventArgs e)
+ {
+
+ grabMouse = false;
+
+ if (activeWidget != null) {
+ activeWidget.ProcessMouseUp (e.Position);
+ }
+ }
+
+ #endregion
+
+ #region keyboard handling
+ public static KeyboardDevice Keyboard;
+ private static bool _capitalOn = false;
+
+ public static bool capitalOn {
+ get {
+ return
+ Keyboard [Key.ShiftLeft] || Keyboard [Key.ShiftRight] ?
+ !_capitalOn : _capitalOn;
+ }
+ set { _capitalOn = value; }
+ }
+
+ public static void ProcessKeyboard (Key k)
+ {
+ switch (k) {
+ case Key.CapsLock:
+ capitalOn = !capitalOn;
+ break;
+ }
+
+ if (activeWidget != null)
+ activeWidget.ProcessKeyboard (k);
+ }
+ #endregion
+
+
+
+
+ //used to manage focusable widget like textboxes or buttons
+ private static GraphicObject _activeWidget;
+
+ public static GraphicObject activeWidget {
+ get { return _activeWidget; }
+ set { _activeWidget = value; }
+ }
+
+ static GraphicObject _hoverWidget;
+
+ public static GraphicObject hoverWidget {
+ get { return _hoverWidget; }
+ set {
+ if (value == _hoverWidget)
+ return;
+
+ _hoverWidget = value;
+ }
+ }
+
+ static Rectangle _renderBounds = new Rectangle(0, 0, 800, 600);
+ public static Rectangle renderBounds
+ {
+ get { return _renderBounds; }
+ set
+ {
+ _renderBounds = value;
+ ctx = null;
+ if (surf != null)
+ surf.Dispose();
+ createOpenGLSurface();
+ foreach (Panel p in panels)
+ {
+ p.invalidateLayout();
+ }
+ }
+ }
+
+ public static Panel addPanel (Rectangle _bounds)
+ {
+ Panel p = new Panel (_bounds);
+ panels.Add (p);
+ return p;
+ }
+
+ public static PanelWithTitle addPanel (Rectangle _bounds, string _title)
+ {
+ PanelWithTitle p = new PanelWithTitle (_bounds);
+ p.title = _title;
+ panels.Add (p);
+ return p;
+ }
+
+ public static int mouseX = 0;
+ public static int mouseY = 0;
+
+ public static void update ()
+ {
+
+
+
+ Stopwatch layoutTime = new Stopwatch ();
+ Stopwatch guTime = new Stopwatch ();
+ Stopwatch drawingTime = new Stopwatch ();
+
+
+ Panel[] inversedPanels = new Panel[panels.Count];
+ panels.CopyTo (inversedPanels);
+ inversedPanels = inversedPanels.Reverse ().ToArray ();
+
+ foreach (Panel p in inversedPanels) {
+ if (p.isVisible) {
+ layoutTime.Start ();
+ p.processkLayouting ();
+ layoutTime.Stop ();
+
+
+ }
+ }
+ lock(redrawClip)
+ {
+ if (redrawClip.count > 0) {
+ redrawClip.clearAndClip (ctx);
+
+
+ foreach (Panel p in inversedPanels) {
+ if (p.isVisible) {
+ drawingTime.Start ();
+
+ ctx.Save ();
+
+ if (redrawClip.count > 0) {
+
+
+ Rectangle r = p.renderBounds;
+ Rectangles clip = redrawClip.intersectingRects (r);
+
+ if (clip.count > 0)
+ p.cairoDraw (ref ctx, clip);
+ //p.processDrawing(ctx);
+ }
+ drawingTime.Stop ();
+
+ ctx.Restore ();
+ }
+ }
+ //ctx.SetSourceSurface (mouseGraphic, mouseX, mouseY);
+ //ctx.Paint ();
+ ctx.ResetClip ();
+ redrawClip.Reset ();
+ }
+
+ }
+
+ //Debug.WriteLine("INTERFACE: layouting: {0} ticks \t graphical update {1} ticks \t drawing {2} ticks",
+ // layoutTime.ElapsedTicks,
+ // guTime.ElapsedTicks,
+ // drawingTime.ElapsedTicks);
+ Debug.WriteLine ("INTERFACE: layouting: {0} ms \t graphical update {1} ms \t drawing {2} ms",
+ layoutTime.ElapsedMilliseconds,
+ guTime.ElapsedMilliseconds,
+ drawingTime.ElapsedMilliseconds);
+
+ }
+
+ public static void setTeint (float colorScale)
+ {
+ GL.PixelTransfer (PixelTransferParameter.RedScale, colorScale);
+ GL.PixelTransfer (PixelTransferParameter.BlueScale, colorScale);
+ GL.PixelTransfer (PixelTransferParameter.GreenScale, colorScale);
+ }
+
+ public static byte[] flitY (byte[] source, int stride, int height)
+ {
+ byte[] bmp = new byte[source.Length];
+ source.CopyTo (bmp, 0);
+
+ for (int y = 0; y < height / 2; y++) {
+ for (int x = 0; x < stride; x++) {
+ byte tmp = bmp [y * stride + x];
+ bmp [y * stride + x] = bmp [(height - 1 - y) * stride + x];
+ bmp [(height - y - 1) * stride + x] = tmp;
+ }
+ }
+ return bmp;
+ }
+
+ public static double min (params double[] arr)
+ {
+ int minp = 0;
+ for (int i = 1; i < arr.Length; i++)
+ if (arr [i] < arr [minp])
+ minp = i;
+
+ return arr [minp];
+ }
+
+ public static void DrawRoundedRectangle (Cairo.Context gr, Rectangle r, double radius)
+ {
+ DrawRoundedRectangle (gr, r.X, r.Y, r.Width, r.Height, radius);
+ }
+
+ public static void DrawCurvedRectangle (Cairo.Context gr, Rectangle r)
+ {
+ DrawCurvedRectangle (gr, r.X, r.Y, r.Width, r.Height);
+ }
+
+ public static void DrawRoundedRectangle (Cairo.Context gr, double x, double y, double width, double height, double radius)
+ {
+ gr.Save ();
+
+ if ((radius > height / 2) || (radius > width / 2))
+ radius = min (height / 2, width / 2);
+
+ gr.MoveTo (x, y + radius);
+ gr.Arc (x + radius, y + radius, radius, Math.PI, -Math.PI / 2);
+ gr.LineTo (x + width - radius, y);
+ gr.Arc (x + width - radius, y + radius, radius, -Math.PI / 2, 0);
+ gr.LineTo (x + width, y + height - radius);
+ gr.Arc (x + width - radius, y + height - radius, radius, 0, Math.PI / 2);
+ gr.LineTo (x + radius, y + height);
+ gr.Arc (x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
+ gr.ClosePath ();
+ gr.Restore ();
+ }
+
+ public static void DrawCurvedRectangle (Cairo.Context gr, double x, double y, double width, double height)
+ {
+ gr.Save ();
+ gr.MoveTo (x, y + height / 2);
+ gr.CurveTo (x, y, x, y, x + width / 2, y);
+ gr.CurveTo (x + width, y, x + width, y, x + width, y + height / 2);
+ gr.CurveTo (x + width, y + height, x + width, y + height, x + width / 2, y + height);
+ gr.CurveTo (x, y + height, x, y + height, x, y + height / 2);
+ gr.Restore ();
+ }
+
+ public static void StrokeRaisedRectangle (Cairo.Context gr, Rectangle r, double width = 1)
+ {
+ gr.Save ();
+ r.Inflate ((int)-width / 2, (int)-width / 2);
+ gr.LineWidth = width;
+ gr.Color = Color.White;
+ gr.MoveTo (r.BottomLeft);
+ gr.LineTo (r.TopLeft);
+ gr.LineTo (r.TopRight);
+ gr.Stroke ();
+
+ gr.Color = Color.DarkGray;
+ gr.MoveTo (r.TopRight);
+ gr.LineTo (r.BottomRight);
+ gr.LineTo (r.BottomLeft);
+ gr.Stroke ();
+
+ gr.Restore ();
+ }
+
+ public static void StrokeLoweredRectangle (Cairo.Context gr, Rectangle r, double width = 1)
+ {
+ gr.Save ();
+ r.Inflate ((int)-width / 2, (int)-width / 2);
+ gr.LineWidth = width;
+ gr.Color = Color.DarkGray;
+ gr.MoveTo (r.BottomLeft);
+ gr.LineTo (r.TopLeft);
+ gr.LineTo (r.TopRight);
+ gr.Stroke ();
+ gr.Color = Color.White;
+ gr.MoveTo (r.TopRight);
+ gr.LineTo (r.BottomRight);
+ gr.LineTo (r.BottomLeft);
+ gr.Stroke ();
+
+ gr.Restore ();
+ }
+ }
+
+
+}