using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace Mjrk.Util.Mouse {
///
/// マウスジェスチャを取得するクラス
///
class MouseGesture {
#region 内部変数
// 基準位置
Point? basePoint;
// 方向のリスト
List value = new List();
// 矢印
string[] arrows = { "", "↑", "↓", "←", "→", "[←↑]", "[→↑]", "[←↓]", "[→↓]" };
// 感度
int interval = 30;
// 斜め認識
bool slant = false;
// 厳密さ
int strict = 3;
// 厳密チェック 以前の方向
Direction strict_before;
// 厳密チェック カウント
int strict_count = 0;
// 重複を許可
bool duplicate = false;
#endregion
#region プロパティ
///
/// ジェスチャの内容
///
public List Value {
get {
return this.value;
}
set {
this.value = value;
}
}
///
/// ジェスチャ判定する間隔。値が少ないほど、細かい動きに反応するようになる。
///
public int Interval {
get {
return this.interval;
}
set {
if (value < 1) { value = 1; }
this.interval = value;
}
}
///
/// 斜めも感知するかどうか
///
public bool Slant {
get { return this.slant; }
set { this.slant = value; }
}
///
/// 厳密さ。値が高いほど、厳しく判定するようになる。
///
public int Strict {
get { return this.strict; }
set {
if (value < 1) { value = 1; }
this.strict = value;
}
}
///
/// 重複を許可。同じ方向に長く動いた場合に重複して軌跡を記録する。
///
public bool Duplicate {
get { return this.duplicate; }
set { this.duplicate = value; }
}
#endregion
#region 公開メソッド
///
/// ジェスチャの記録開始
///
public void Start() {
this.basePoint = null;
this.value.Clear();
}
///
/// ジェスチャ中に現在のポインタの位置を記録
///
/// 現在のマウスポインタの位置
public void Moving(Point point) {
if (this.basePoint == null) { this.basePoint = (Point?)point; }
Direction dir = this.JudgeDirection(point, (Point)this.basePoint);
if (dir == Direction.None) { return; }
if (this.strict_before == dir) { this.strict_count++; }
else { this.strict_before = dir; this.strict_count = 0; }
if (this.strict_count >= this.strict
&& (this.duplicate || (this.value.Count == 0 || this.value[this.value.Count - 1] != dir))) {
this.value.Add(dir);
this.strict_count = 0;
}
this.basePoint = null;
}
///
/// ジェスチャの文字列表現
///
/// 矢印記号で表した現在のジェスチャ
public override string ToString() {
StringBuilder strb = new StringBuilder();
foreach (Direction d in this.value) {
strb.Append(this.arrows[(int)d]);
}
return strb.ToString();
}
#endregion
#region 非公開メソッド
///
/// 方向を判断
///
/// 現在のポインタの位置
/// 基準となるポインタの位置
/// 方向
protected Direction JudgeDirection(Point a, Point b) {
if ((int)(Math.Sqrt(Math.Pow(Math.Abs(a.X - b.X), 2) + Math.Pow(Math.Abs(a.Y - b.Y), 2))) < this.Interval / this.Strict) {
return Direction.None;
}
double dir = Math.Abs(a.X - b.X) / (Math.Abs(a.Y - b.Y) + 0.0001);
if (this.Slant && dir > 0.4 && dir < 1.6) {
if (a.X > b.X) {
if (a.Y > b.Y) { return Direction.BottomRight; }
else { return Direction.TopRight; }
}
else {
if (a.Y > b.Y) { return Direction.BottomLeft; }
else { return Direction.TopLeft; }
}
}
if (dir > 1) {
if (a.X > b.X) { return Direction.Right; }
else { return Direction.Left; }
}
else {
if (a.Y > b.Y) { return Direction.Bottom; }
else { return Direction.Top; }
}
}
#endregion
}
///
/// 方向を表す列挙型
///
public enum Direction {
///
/// 無指向
///
None = 0,
///
/// 上方向
///
Top = 1,
///
/// 下方向
///
Bottom = 2,
///
/// 左方向
///
Left = 3,
///
/// 右方向
///
Right = 4,
///
/// 左上
///
TopLeft = 5,
///
/// 右上
///
TopRight = 6,
///
/// 左下
///
BottomLeft = 7,
///
/// 右下
///
BottomRight = 8
}
}