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.
tdeaccessibility/kmousetool/kmousetool/mtstroke.cpp

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);
}