|
|
ebcc4f |
using System;
|
|
|
ebcc4f |
using System.Collections.Generic;
|
|
|
ebcc4f |
|
|
|
ebcc4f |
namespace Assistance {
|
|
|
b82ef4 |
public class MainWindow : Gtk.Window {
|
|
|
b82ef4 |
static public void Main() {
|
|
|
b82ef4 |
Gtk.Application.Init();
|
|
|
b82ef4 |
MainWindow win = new MainWindow();
|
|
|
6148f0 |
win.Show();
|
|
|
6148f0 |
win.Maximize();
|
|
|
b82ef4 |
Gtk.Application.Run();
|
|
|
b82ef4 |
}
|
|
|
b82ef4 |
|
|
|
b82ef4 |
Cairo.ImageSurface surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, 1, 1);
|
|
|
ebcc4f |
|
|
|
b1ff53 |
Workarea workarea = new Workarea();
|
|
|
b9e5e0 |
ToolFull toolFull;
|
|
|
b9e5e0 |
|
|
|
ebcc4f |
bool dragging = false;
|
|
|
b9e5e0 |
bool painting = false;
|
|
|
ebcc4f |
ActivePoint activePoint;
|
|
|
b82ef4 |
|
|
|
ebcc4f |
Point offset;
|
|
|
ebcc4f |
Point cursor;
|
|
|
b1ff53 |
|
|
|
b9e5e0 |
long touchId;
|
|
|
b9e5e0 |
long ticksStart = 0;
|
|
|
b9e5e0 |
double timeStart = 0;
|
|
|
c66393 |
|
|
|
b82ef4 |
public MainWindow(): base(Gtk.WindowType.Toplevel) {
|
|
|
6148f0 |
foreach(Gdk.Device device in Display.ListDevices()) {
|
|
|
6148f0 |
if (device.Name.Contains("tylus")) {
|
|
|
6148f0 |
device.SetMode(Gdk.InputMode.Screen);
|
|
|
6148f0 |
break;
|
|
|
6148f0 |
}
|
|
|
6148f0 |
}
|
|
|
6148f0 |
|
|
|
6148f0 |
Events = Gdk.EventMask.KeyPressMask
|
|
|
6148f0 |
| Gdk.EventMask.KeyReleaseMask
|
|
|
6148f0 |
| Gdk.EventMask.ButtonPressMask
|
|
|
6148f0 |
| Gdk.EventMask.ButtonReleaseMask
|
|
|
6148f0 |
| Gdk.EventMask.ButtonMotionMask
|
|
|
6148f0 |
| Gdk.EventMask.PointerMotionMask;
|
|
|
6148f0 |
ExtensionEvents = Gdk.ExtensionMode.All;
|
|
|
b9e5e0 |
|
|
|
b9e5e0 |
toolFull = new ToolFull(workarea);
|
|
|
b9e5e0 |
workarea.setTool(toolFull);
|
|
|
ebcc4f |
}
|
|
|
b82ef4 |
|
|
|
b82ef4 |
protected override bool OnDeleteEvent(Gdk.Event e) {
|
|
|
b82ef4 |
Gtk.Application.Quit();
|
|
|
b82ef4 |
return true;
|
|
|
b82ef4 |
}
|
|
|
ebcc4f |
|
|
|
b82ef4 |
protected override void OnSizeAllocated(Gdk.Rectangle allocation) {
|
|
|
b82ef4 |
if ( surface.Width != allocation.Width
|
|
|
b82ef4 |
|| surface.Height != allocation.Height )
|
|
|
b82ef4 |
{
|
|
|
b82ef4 |
surface.Dispose();
|
|
|
b82ef4 |
surface = new Cairo.ImageSurface(Cairo.Format.ARGB32, allocation.Width, allocation.Height);
|
|
|
b82ef4 |
}
|
|
|
b82ef4 |
base.OnSizeAllocated(allocation);
|
|
|
b82ef4 |
}
|
|
|
ebcc4f |
|
|
|
b82ef4 |
protected override bool OnExposeEvent(Gdk.EventExpose e) {
|
|
|
b82ef4 |
Cairo.Context context = new Cairo.Context(surface);
|
|
|
b82ef4 |
context.Antialias = Cairo.Antialias.Gray;
|
|
|
b82ef4 |
|
|
|
b82ef4 |
context.Save();
|
|
|
b82ef4 |
context.SetSourceRGBA(1.0, 1.0, 1.0, 1.0);
|
|
|
b82ef4 |
context.Rectangle(0, 0, surface.Width, surface.Height);
|
|
|
b82ef4 |
context.Fill();
|
|
|
b82ef4 |
context.Restore();
|
|
|
b82ef4 |
|
|
|
b82ef4 |
draw(context);
|
|
|
b82ef4 |
context.Dispose();
|
|
|
b82ef4 |
|
|
|
b82ef4 |
context = Gdk.CairoHelper.Create(GdkWindow);
|
|
|
b82ef4 |
context.SetSource(surface);
|
|
|
b82ef4 |
context.Paint();
|
|
|
b82ef4 |
context.Dispose();
|
|
|
b82ef4 |
|
|
|
b82ef4 |
return true;
|
|
|
b82ef4 |
}
|
|
|
ebcc4f |
|
|
|
b1ff53 |
public Point windowToWorkarea(Point p) {
|
|
|
b82ef4 |
return new Point(p.x - surface.Width/2.0, p.y - surface.Height/2.0);
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
|
|
|
b1ff53 |
public Point workareaToWindow(Point p) {
|
|
|
b82ef4 |
return new Point(p.x + surface.Width/2.0, p.y + surface.Height/2.0);
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
|
|
|
ebcc4f |
private void beginDrag() {
|
|
|
b1ff53 |
endDragAndTrack();
|
|
|
ebcc4f |
dragging = true;
|
|
|
ebcc4f |
offset = activePoint.position - cursor;
|
|
|
ebcc4f |
activePoint.bringToFront();
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
|
|
|
b9e5e0 |
private void beginTrack(double timeStart) {
|
|
|
b1ff53 |
endDragAndTrack();
|
|
|
b9e5e0 |
++touchId;
|
|
|
c66393 |
ticksStart = Timer.ticks();
|
|
|
b9e5e0 |
this.timeStart = timeStart;
|
|
|
b1ff53 |
}
|
|
|
b1ff53 |
|
|
|
b1ff53 |
private void endDragAndTrack() {
|
|
|
ebcc4f |
dragging = false;
|
|
|
ebcc4f |
offset = new Point();
|
|
|
b9e5e0 |
if (painting) {
|
|
|
b9e5e0 |
painting = false;
|
|
|
b9e5e0 |
workarea.inputManager.finishTracks();
|
|
|
b9e5e0 |
}
|
|
|
ebcc4f |
}
|
|
|
b82ef4 |
|
|
|
b82ef4 |
protected override bool OnKeyPressEvent(Gdk.EventKey e) {
|
|
|
b82ef4 |
switch(e.Key) {
|
|
|
b82ef4 |
case Gdk.Key.Key_1:
|
|
|
726e8a |
new AssistantVanishingPoint(workarea.document, cursor);
|
|
|
c66393 |
endDragAndTrack();
|
|
|
ebcc4f |
break;
|
|
|
b82ef4 |
case Gdk.Key.Q:
|
|
|
b82ef4 |
case Gdk.Key.q:
|
|
|
726e8a |
new ModifierSnowflake(workarea.document, cursor);
|
|
|
c66393 |
endDragAndTrack();
|
|
|
72b17c |
break;
|
|
|
6148f0 |
case Gdk.Key.I:
|
|
|
6148f0 |
case Gdk.Key.i:
|
|
|
6148f0 |
Gtk.InputDialog dialog = new Gtk.InputDialog();
|
|
|
6148f0 |
dialog.CloseButton.Clicked += (object sender, EventArgs args) => { dialog.Destroy(); };
|
|
|
6148f0 |
dialog.Show();
|
|
|
6148f0 |
break;
|
|
|
b82ef4 |
case Gdk.Key.Delete:
|
|
|
ebcc4f |
if (activePoint != null)
|
|
|
72b17c |
activePoint.owner.remove();
|
|
|
b1ff53 |
endDragAndTrack();
|
|
|
ebcc4f |
break;
|
|
|
c66393 |
default:
|
|
|
b9e5e0 |
workarea.inputManager.keyEvent(true, e.Key, Timer.ticks());
|
|
|
c66393 |
break;
|
|
|
ebcc4f |
}
|
|
|
b82ef4 |
QueueDraw();
|
|
|
b82ef4 |
return base.OnKeyPressEvent(e);
|
|
|
b82ef4 |
}
|
|
|
b82ef4 |
|
|
|
c66393 |
protected override bool OnKeyReleaseEvent(Gdk.EventKey e) {
|
|
|
b9e5e0 |
workarea.inputManager.keyEvent(false, e.Key, Timer.ticks());
|
|
|
c66393 |
return base.OnKeyReleaseEvent(e);
|
|
|
c66393 |
}
|
|
|
c66393 |
|
|
|
b9e5e0 |
void addTrackPoint(Gdk.Device device, Point p, double time, double pressure, Point tilt, bool final) {
|
|
|
b9e5e0 |
if (!painting)
|
|
|
c66393 |
return;
|
|
|
c66393 |
|
|
|
b9e5e0 |
Track.Point point = new Track.Point();
|
|
|
b9e5e0 |
point.position = p;
|
|
|
c66393 |
point.pressure = pressure;
|
|
|
b9e5e0 |
point.tilt = tilt;
|
|
|
c66393 |
|
|
|
b9e5e0 |
long ticks = ticksStart + (long)Math.Round((time - timeStart)*Timer.frequency);
|
|
|
c66393 |
|
|
|
b9e5e0 |
workarea.inputManager.trackEvent(device, touchId, point, final, ticks);
|
|
|
c66393 |
}
|
|
|
c66393 |
|
|
|
b9e5e0 |
void addTrackPoint(double x, double y, uint t, Gdk.Device device, double[] axes, bool final) {
|
|
|
c66393 |
Point point = windowToWorkarea(new Point(x, y));
|
|
|
c66393 |
double time = (double)(t - timeStart)*0.001;
|
|
|
c66393 |
double pressure = 0.5;
|
|
|
c66393 |
Point tilt = new Point(0.0, 0.0);
|
|
|
b82ef4 |
if (device != null && axes != null) {
|
|
|
b82ef4 |
double v;
|
|
|
b82ef4 |
if (device.GetAxis(axes, Gdk.AxisUse.Pressure, out v))
|
|
|
c66393 |
pressure = v;
|
|
|
b82ef4 |
if (device.GetAxis(axes, Gdk.AxisUse.Xtilt, out v))
|
|
|
c66393 |
tilt.x = v;
|
|
|
b82ef4 |
if (device.GetAxis(axes, Gdk.AxisUse.Ytilt, out v))
|
|
|
c66393 |
tilt.y = v;
|
|
|
b82ef4 |
}
|
|
|
b9e5e0 |
addTrackPoint(device, point, time, pressure, tilt, final);
|
|
|
c66393 |
}
|
|
|
c66393 |
|
|
|
b9e5e0 |
void addTrackPoint(Gdk.EventButton e, bool press)
|
|
|
b9e5e0 |
{ addTrackPoint(e.X, e.Y, e.Time, e.Device, e.Axes, !press); }
|
|
|
b9e5e0 |
void addTrackPoint(Gdk.EventMotion e)
|
|
|
b9e5e0 |
{ addTrackPoint(e.X, e.Y, e.Time, e.Device, e.Axes, false); }
|
|
|
b82ef4 |
|
|
|
b82ef4 |
protected override bool OnButtonPressEvent(Gdk.EventButton e) {
|
|
|
b82ef4 |
cursor = windowToWorkarea(new Point(e.X, e.Y));
|
|
|
b9e5e0 |
workarea.inputManager.buttonEvent(true, e.Device, e.Button, Timer.ticks());
|
|
|
b82ef4 |
if (e.Button == 1) {
|
|
|
b82ef4 |
timeStart = e.Time;
|
|
|
b1ff53 |
activePoint = workarea.findPoint(cursor);
|
|
|
b1ff53 |
if (activePoint != null) {
|
|
|
ebcc4f |
beginDrag();
|
|
|
b1ff53 |
} else {
|
|
|
b9e5e0 |
beginTrack((double)e.Time*0.001);
|
|
|
b9e5e0 |
addTrackPoint(e, true);
|
|
|
b1ff53 |
}
|
|
|
ebcc4f |
}
|
|
|
b82ef4 |
QueueDraw();
|
|
|
b82ef4 |
return true;
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
|
|
|
b82ef4 |
protected override bool OnButtonReleaseEvent(Gdk.EventButton e) {
|
|
|
b1ff53 |
cursor = windowToWorkarea(new Point(e.X, e.Y));
|
|
|
b9e5e0 |
workarea.inputManager.buttonEvent(false, e.Device, e.Button, Timer.ticks());
|
|
|
b82ef4 |
if (e.Button == 1) {
|
|
|
b9e5e0 |
if (!dragging && painting)
|
|
|
b9e5e0 |
addTrackPoint(e, false);
|
|
|
b1ff53 |
endDragAndTrack();
|
|
|
b9e5e0 |
if (!dragging && !painting)
|
|
|
b82ef4 |
activePoint = workarea.findPoint(cursor);
|
|
|
b82ef4 |
}
|
|
|
b82ef4 |
QueueDraw();
|
|
|
b82ef4 |
return true;
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
|
|
|
b82ef4 |
protected override bool OnMotionNotifyEvent(Gdk.EventMotion e) {
|
|
|
b82ef4 |
cursor = windowToWorkarea(new Point(e.X, e.Y));
|
|
|
ebcc4f |
if (dragging) {
|
|
|
72b17c |
activePoint.owner.onMovePoint(activePoint, cursor + offset);
|
|
|
b1ff53 |
} else
|
|
|
b9e5e0 |
if (painting) {
|
|
|
c66393 |
addTrackPoint(e);
|
|
|
ebcc4f |
} else {
|
|
|
b1ff53 |
activePoint = workarea.findPoint(cursor);
|
|
|
ebcc4f |
}
|
|
|
b82ef4 |
QueueDraw();
|
|
|
b82ef4 |
return true;
|
|
|
b82ef4 |
}
|
|
|
ebcc4f |
|
|
|
b82ef4 |
public void draw(Cairo.Context context) {
|
|
|
b82ef4 |
context.Translate(surface.Width/2, surface.Height/2);
|
|
|
b9e5e0 |
workarea.draw(context, activePoint);
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
}
|
|
|
ebcc4f |
}
|