You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
8.1 KiB
289 lines
8.1 KiB
/***************************************************************************
|
|
mtstroke.cpp - description
|
|
-------------------
|
|
begin : Fri Oct 11 2002
|
|
copyright : (C) 2002 by Jeff Roush
|
|
email : jeff@mousetool.com
|
|
copyright : (C) 2003 by Olaf Schmidt
|
|
email : ojschmidt@kde.org
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "mtstroke.h"
|
|
#include "kmousetool.h"
|
|
#include <iostream>
|
|
|
|
// these are for locating the stroke information file
|
|
#include <kstandarddirs.h>
|
|
#include <tqstring.h>
|
|
|
|
// #include <string>
|
|
|
|
using namespace std;
|
|
|
|
const int MTStroke::DontClick = -1;
|
|
const int MTStroke::bumped_mouse = 0;
|
|
const int MTStroke::normal = 1;
|
|
const int MTStroke::RightClick = 2;
|
|
const int MTStroke::DoubleClick = 3;
|
|
const int MTStroke::circle = 4;
|
|
const int MTStroke::LowerLeftStroke = 5;
|
|
const int MTStroke::UpperRightStroke = 6;
|
|
const int MTStroke::LowerRightStroke = 7;
|
|
const int MTStroke::UpperLeftStroke = 8;
|
|
|
|
int MTStroke::delta_xy = 10;
|
|
|
|
const int MTStroke::min_num_points = 5;
|
|
|
|
Pt MTStroke::LowerLeft (0,0);
|
|
Pt MTStroke::LowerRight(0,0);
|
|
Pt MTStroke::UpperLeft (0,0);
|
|
Pt MTStroke::UpperRight(0,0);
|
|
|
|
|
|
|
|
MTStroke::MTStroke(){
|
|
readSequence();
|
|
}
|
|
MTStroke::~MTStroke(){
|
|
}
|
|
|
|
// add the new point, but only if it's not the same as the previous point.
|
|
void MTStroke::addPt(const int x, const int y)
|
|
{
|
|
if (points.size()==0) {
|
|
points.push_back(Pt(x,y));
|
|
}
|
|
else {
|
|
Pt pt(x,y);
|
|
if (!pt.sameAs(points[points.size()-1])) {
|
|
points.push_back(Pt(x,y));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Loop over all the strokes;
|
|
* return true if the given point is included
|
|
*/
|
|
bool MTStroke::pointsContain(Pt pt)
|
|
{
|
|
std::vector<Pt>::iterator pos;
|
|
for (pos=points.begin(); pos<points.end(); pos++) {
|
|
if (pt.x==pos->x && pt.y==pos->y)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int MTStroke::getStrokeType()
|
|
{
|
|
int size = points.size();
|
|
|
|
// If the mouse moved just a bit, it was probably bumped. Don't click.
|
|
if (size<min_num_points)
|
|
return normal;
|
|
// return bumped_mouse;
|
|
|
|
Pt lastPoint = points[points.size()-1];
|
|
|
|
// If the mouse is pausing in a corner, then the user is either in the middle of a
|
|
// stroke, or wants to rest the mouse. Don't click.
|
|
if (lastPoint.sameAs(LowerLeft) || lastPoint.sameAs(LowerRight)
|
|
|| lastPoint.sameAs(UpperLeft) || lastPoint.sameAs(UpperRight))
|
|
return DontClick;
|
|
|
|
// If the mouse visited a corner...
|
|
if (pointsContain(LowerLeft)) {
|
|
reset();
|
|
return LowerLeftStroke;
|
|
}
|
|
if (pointsContain(UpperRight)) {
|
|
reset();
|
|
return UpperRightStroke;
|
|
}
|
|
scale();
|
|
|
|
std::map<std::string, int>::iterator keypos = sequenceMap.find(sequence);
|
|
if (keypos == sequenceMap.end()) {
|
|
reset();
|
|
return normal;
|
|
}
|
|
reset();
|
|
// return RightClick;
|
|
return keypos->second;
|
|
}
|
|
|
|
void MTStroke::scale()
|
|
{
|
|
getExtent();
|
|
int deltax = stroke_maxx - stroke_minx;
|
|
int deltay = stroke_maxy - stroke_miny;
|
|
int delta = max(deltax, deltay);
|
|
int scale = (int) delta/2;
|
|
|
|
std::vector<Pt>::iterator pos;
|
|
for (pos=points.begin(); pos<points.end(); pos++) {
|
|
|
|
// add an extra (scale/2) because the divide rounds _down_, and we want to
|
|
// round _up_ or _down_, depending on which is closer.
|
|
pos->x = (int) (pos->x-stroke_minx + scale/2)/scale;
|
|
pos->y = (int) (pos->y-stroke_miny + scale/2)/scale;
|
|
|
|
// now, get the integer representing this position and add it to the stroke sequence
|
|
int n = 3*pos->y + pos->x + 1;
|
|
int index = sequence.size()-1;
|
|
n += '0';
|
|
if (index==-1)
|
|
sequence += n;
|
|
else if (n!=sequence[index])
|
|
sequence += n;
|
|
}
|
|
}
|
|
|
|
int MTStroke::max(int n, int m)
|
|
{
|
|
if (n>m)
|
|
return n;
|
|
return m;
|
|
}
|
|
|
|
|
|
/*
|
|
* Find the bounding rectangle for the stroke
|
|
*/
|
|
void MTStroke::getExtent()
|
|
{
|
|
stroke_minx = UpperRight.x;
|
|
stroke_maxx = 0;
|
|
stroke_miny = LowerLeft.y;
|
|
stroke_maxy = 0;
|
|
|
|
std::vector<Pt>::iterator pos;
|
|
for (pos=points.begin(); pos<points.end(); pos++) {
|
|
if (stroke_minx > pos->x)
|
|
stroke_minx = pos->x;
|
|
if (stroke_maxx < pos->x)
|
|
stroke_maxx = pos->x;
|
|
if (stroke_miny > pos->y)
|
|
stroke_miny = pos->y;
|
|
if (stroke_maxy < pos->y)
|
|
stroke_maxy = pos->y;
|
|
}
|
|
}
|
|
|
|
// test if strokefile exists; if not, create it from defaults.
|
|
// if unable to create it,
|
|
bool MTStroke::readSequence()
|
|
{
|
|
TQString strokefilename;
|
|
strokefilename = locate("config", "kmousetool_strokes.txt");
|
|
if (strokefilename.isEmpty()) {
|
|
// make default
|
|
if (sequenceMap.size()==0)
|
|
makeDefaultSequenceMap();
|
|
writeSequence();
|
|
return false;
|
|
}
|
|
ifstream infile (strokefilename.ascii());
|
|
if (!infile) {
|
|
// make default
|
|
if (sequenceMap.size()==0)
|
|
makeDefaultSequenceMap();
|
|
writeSequence();
|
|
return false;
|
|
}
|
|
|
|
while (!infile.eof()) {
|
|
string str;
|
|
infile >> str;
|
|
if (str[0] == '#')
|
|
readToEndOfLine(infile);
|
|
else {
|
|
// get the associated action
|
|
string str2;
|
|
infile >> str2;
|
|
int n = str2[0] - '0'; // the action is a single integer digit; convert it to an int
|
|
sequenceMap[ string(str) ] = n;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool MTStroke::writeSequence()
|
|
{
|
|
TQString strokefilename;
|
|
strokefilename = locateLocal("config", "kmousetool_strokes.txt");
|
|
|
|
ofstream outfile (strokefilename.ascii(), ios::out);
|
|
if (!outfile) {
|
|
return false;
|
|
}
|
|
|
|
outfile << "# This file contains definitions for valid strokes for KMouseTool\n";
|
|
outfile << "# To make sense of the numbers: \n";
|
|
outfile << "# The mouse path begins and ends when the mouse is paused.\n";
|
|
outfile << "# Imagine a square enclosing the path.\n";
|
|
outfile << "# Divide the square into 9 boxes, and number them like so:\n";
|
|
outfile << "# 1 2 3\n";
|
|
outfile << "# 4 5 6\n";
|
|
outfile << "# 7 8 9\n";
|
|
outfile << "# \n";
|
|
outfile << "# The mouse path can then be described by a sequence of numbers:\n";
|
|
outfile << "# for example, \"12321\" describes the mouse moving from left to right and back.\n";
|
|
outfile << "# This general scheme follows libstroke (http://www.etla.net/~willey/projects/libstroke/)\n";
|
|
outfile << "# although it was reimplemented from scratch for KMouseTool.\n";
|
|
outfile << "\n";
|
|
outfile << "# For each stroke recognized, provide an integer describing an action\n";
|
|
outfile << "# KMouseTool can take. At the moment, valid actions are:\n";
|
|
outfile << "# -1 Don't click\n";
|
|
outfile << "# 1 Normal click (use Smart Drag if that's enabled)\n";
|
|
outfile << "# 2 Right click\n";
|
|
outfile << "# 3 Double click\n";
|
|
outfile << "\n";
|
|
outfile << "#Stroke\tAction\n";
|
|
std::map<std::string, int>::iterator pos = sequenceMap.begin();
|
|
while (pos != sequenceMap.end()) {
|
|
outfile << pos->first << "\t" << pos->second << "\n";
|
|
pos++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MTStroke::makeDefaultSequenceMap()
|
|
{
|
|
sequenceMap[ string("12321") ] = RightClick;
|
|
sequenceMap[ string("1321") ] = RightClick;
|
|
sequenceMap[ string("1231") ] = RightClick;
|
|
sequenceMap[ string("131") ] = RightClick;
|
|
|
|
sequenceMap[ string("32123") ] = DoubleClick;
|
|
sequenceMap[ string("3213") ] = DoubleClick;
|
|
sequenceMap[ string("3123") ] = DoubleClick;
|
|
sequenceMap[ string("313") ] = DoubleClick;
|
|
/*
|
|
sequenceMap[ string("") ] = ;
|
|
sequenceMap[ string("") ] = ;
|
|
sequenceMap[ string("") ] = ;
|
|
sequenceMap[ string("") ] = ;
|
|
sequenceMap[ string("") ] = ;
|
|
*/
|
|
}
|
|
|
|
void MTStroke::readToEndOfLine(ifstream &infile)
|
|
{
|
|
char ch = 'a';
|
|
while (ch != '\n')
|
|
infile.get(ch);
|
|
}
|