Skip to content

Commit

Permalink
🎉 Add experimental fixed-stroke-length mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Schneegans committed Oct 25, 2024
1 parent da731a9 commit 0c7374f
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ This changelog follows the rules of [Keep a Changelog](http://keepachangelog.com
- **Support for base64 icons:** This allows you to directly embed base64 encoded images. This will be especially helpful for menus which are dynamically generated via some sort of API in the future. Use `"base64"` as the icon theme and provide the base64 encoded image as the `"icon"`. This will be a string starting with something like `"data:image/svg+xml;base64, ..."`. This even supports animated gifs!
- **Version information in the sidebar:** The sidebar now shows some version information in the development tab. This includes the version of Kando, the version of Electron, and the currently used backend.
- An option to the menu editor which **allows warping the mouse pointer to the center of the menu** when the menu is opened in centered mode. This allows to directly engage in turbo mode even if the menu is shown at the center of the screen.
- **An experimental Fixed-Stroke-Length Mode:** If you set `"menuOptions": {"fixedStrokeLength": <number of pixels>}` to a value greater than 0, Marking Mode and Turbo will be disabled. Instead, submenus will be opened when the mouse is moved the given distance from the center of the menu.
- **Adjustable fade-in and fade-out duration of the menu:** For now, it is only possible to change this via the `"menuOptions": {"fadeInDuration": 150}` and `"menuOptions": {"fadeOutDuration": 250}` properties in the `config.json` file. In the future, this will be exposed in the settings UI.
- **Possibility to hide sidebar and editor buttons:** You can now add
```json
Expand Down
1 change: 1 addition & 0 deletions docs/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Property | Default Value | Description
`gestureMinStrokeAngle` | `20` | Smaller turns will not lead to selections (in degrees).
`gestureJitterThreshold` | `10` | Smaller pointer movements will not be considered at all during gesture recognition (in pixels).
`gesturePauseTimeout` | `100` | If the pointer is stationary for this many milliseconds, the current item will be selected during gesture recognition.
`fixedStrokeLength` | `0` | If set to a value greater than 0, items will be instantly selected if the mouse travelled more than `centerDeadZone` + `fixedStrokeLength` pixels in marking or turbo mode. Any other gesture detection based on angles or motion speed will be disabled in this case.
`rmbSelectsParent` | `false` | If enabled, the parent of a selected item will be selected on a right mouse button click. Else the menu will be closed directly.

### The `editorOptions` Property
Expand Down
1 change: 1 addition & 0 deletions src/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export class KandoApp {
gestureMinStrokeAngle: 20,
gestureJitterThreshold: 10,
gesturePauseTimeout: 100,
fixedStrokeLength: 0,
rmbSelectsParent: false,
},
editorOptions: {
Expand Down
30 changes: 30 additions & 0 deletions src/renderer/menu/input-methods/gesture-detector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ export class GestureDetector extends EventEmitter {
*/
public pauseTimeout = 100;

/**
* This is used if fixedStrokeLength is greater than zero to allow for distance-based
* selections.
*/
public centerDeadZone = 50;

/**
* If set to a value greater than 0, items will be instantly selected if the mouse
* travelled more than centerDeadZone + fixedStrokeLength pixels in marking or turbo
* mode. Any other gesture detection based on angles or motion speed will be disabled in
* this case.
*/
public fixedStrokeLength = 0;

/**
* This method detects the gestures. It should be called if the mouse pointer was moved
* while the left mouse button is held down. Consider the diagram below:
Expand Down Expand Up @@ -85,6 +99,22 @@ export class GestureDetector extends EventEmitter {

const strokeLength = math.getLength(strokeDir);

// If fixedStrokeLength is set, we only need to check if the stroke is long enough.
if (this.fixedStrokeLength > 0) {
const minStrokeLength = this.fixedStrokeLength + this.centerDeadZone;
if (strokeLength > minStrokeLength) {
const idealCoords = {
x: this.strokeStart.x + (strokeDir.x / strokeLength) * minStrokeLength,
y: this.strokeStart.y + (strokeDir.y / strokeLength) * minStrokeLength,
};

this.reset(idealCoords);
this.emit('selection', idealCoords);
}
this.strokeEnd = coords;
return;
}

if (strokeLength > this.minStrokeLength) {
// Calculate the vector E->M in the diagram above.
const tipDir = { x: coords.x - this.strokeEnd.x, y: coords.y - this.strokeEnd.y };
Expand Down
10 changes: 10 additions & 0 deletions src/renderer/menu/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ export class MenuOptions {
*/
gesturePauseTimeout = 100;

/**
* If set to a value greater than 0, items will be instantly selected if the mouse
* travelled more than centerDeadZone + fixedStrokeLength pixels in marking or turbo
* mode. Any other gesture detection based on angles or motion speed will be disabled in
* this case.
*/
fixedStrokeLength = 0;

/**
* If enabled, the parent of a selected item will be selected on a right mouse button
* click. Else the menu will be closed directly.
Expand Down Expand Up @@ -392,6 +400,8 @@ export class Menu extends EventEmitter {
this.pointerInput.gestureDetector.jitterThreshold =
this.options.gestureJitterThreshold;
this.pointerInput.gestureDetector.pauseTimeout = this.options.gesturePauseTimeout;
this.pointerInput.gestureDetector.fixedStrokeLength = this.options.fixedStrokeLength;
this.pointerInput.gestureDetector.centerDeadZone = this.options.centerDeadZone;
}

// --------------------------------------------------------------------- private methods
Expand Down

0 comments on commit 0c7374f

Please sign in to comment.