add first implementation of circle keyboard and better switching of keyboards
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use enigo::{Direction::Click, Enigo, Key, Keyboard, Settings};
|
use enigo::{Direction, Enigo, Key, Keyboard, Settings};
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
@@ -6,8 +6,8 @@ use tauri::Manager;
|
|||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn greet(name: &str) -> String {
|
fn greet(name: &str) -> String {
|
||||||
let mut enigo = Enigo::new(&Settings::default()).unwrap();
|
// let mut enigo = Enigo::new(&Settings::default()).unwrap();
|
||||||
enigo.key(Key::Unicode('a'), Click);
|
// enigo.key(Key::Unicode('a'), Click);
|
||||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,17 +16,30 @@ fn send_key(key: String) -> Result<(), String> {
|
|||||||
let mut enigo = Enigo::new(&Settings::default()).map_err(|e| format!("Enigo error: {}", e))?;
|
let mut enigo = Enigo::new(&Settings::default()).map_err(|e| format!("Enigo error: {}", e))?;
|
||||||
|
|
||||||
if key.len() == 1 {
|
if key.len() == 1 {
|
||||||
// Single letter (a-z, A-Z)
|
let ch = key.chars().next().unwrap();
|
||||||
enigo.key(Key::Unicode(key.chars().next().unwrap()), Click)
|
|
||||||
|
// Check if uppercase letter
|
||||||
|
if ch.is_uppercase() && ch.is_alphabetic() {
|
||||||
|
// Send Shift + lowercase letter
|
||||||
|
enigo.key(Key::Shift, Direction::Press)
|
||||||
|
.map_err(|e| format!("Shift press error: {}", e))?;
|
||||||
|
enigo.key(Key::Unicode(ch.to_lowercase().next().unwrap()), Direction::Click)
|
||||||
.map_err(|e| format!("Key error: {}", e))?;
|
.map_err(|e| format!("Key error: {}", e))?;
|
||||||
|
enigo.key(Key::Shift, Direction::Release)
|
||||||
|
.map_err(|e| format!("Shift release error: {}", e))?;
|
||||||
|
} else {
|
||||||
|
// Send character as-is (lowercase or non-letter)
|
||||||
|
enigo.key(Key::Unicode(ch), Direction::Click)
|
||||||
|
.map_err(|e| format!("Key error: {}", e))?;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Special keys
|
// Special keys
|
||||||
match key.as_str() {
|
match key.as_str() {
|
||||||
"Enter" => enigo.key(Key::Return, Click)
|
"Enter" => enigo.key(Key::Return, Direction::Click)
|
||||||
.map_err(|e| format!("Key error: {}", e))?,
|
.map_err(|e| format!("Key error: {}", e))?,
|
||||||
"Space" => enigo.key(Key::Space, Click)
|
"Space" => enigo.key(Key::Space, Direction::Click)
|
||||||
.map_err(|e| format!("Key error: {}", e))?,
|
.map_err(|e| format!("Key error: {}", e))?,
|
||||||
"Backspace" => enigo.key(Key::Backspace, Click)
|
"Backspace" => enigo.key(Key::Backspace, Direction::Click)
|
||||||
.map_err(|e| format!("Key error: {}", e))?,
|
.map_err(|e| format!("Key error: {}", e))?,
|
||||||
_ => return Err("Unknown key".to_string()),
|
_ => return Err("Unknown key".to_string()),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,65 +3,35 @@
|
|||||||
<input #greetInput id="greet-input" placeholder="Enter a name..." />
|
<input #greetInput id="greet-input" placeholder="Enter a name..." />
|
||||||
<button type="submit">Greet</button>
|
<button type="submit">Greet</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<p>{{ greetingMessage }}</p>
|
<p>{{ greetingMessage }}</p>
|
||||||
<div class="keyboard">
|
|
||||||
<!-- Row 1-->
|
<!-- Layout Switcher -->
|
||||||
<div class="keyboard-row">
|
<div class="layout-controls">
|
||||||
<button *ngFor="let key of row1"
|
<button (click)="switchLayout()" class="layout-button">
|
||||||
(click)="sendKey(key)"
|
Switch Layout: {{ currentLayout.toUpperCase() }}
|
||||||
class="key-button">
|
|
||||||
{{ shiftActive ? key : key.toLowerCase() }}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Row 2-->
|
<!-- Conditional Rendering basierend auf currentLayout -->
|
||||||
<div class="keyboard-row">
|
<app-qwerty-keyboard
|
||||||
<button *ngFor="let key of row2"
|
*ngIf="currentLayout === 'qwerty'"
|
||||||
(click)="sendKey(key)"
|
[shiftActive]="shiftActive"
|
||||||
class="key-button">
|
(keyPressed)="handleKeyPress($event)"
|
||||||
{{ shiftActive ? key : key.toLowerCase() }}
|
(shiftToggled)="toggleShift()">
|
||||||
</button>
|
</app-qwerty-keyboard>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Row 3-->
|
<app-dvorak-keyboard
|
||||||
<div class="keyboard-row">
|
*ngIf="currentLayout === 'dvorak'"
|
||||||
<button *ngFor="let key of row3"
|
[shiftActive]="shiftActive"
|
||||||
(click)="sendKey(key)"
|
(keyPressed)="handleKeyPress($event)"
|
||||||
class="key-button">
|
(shiftToggled)="toggleShift()">
|
||||||
{{ shiftActive ? key : key.toLowerCase() }}
|
</app-dvorak-keyboard>
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Row 4: special keys -->
|
<app-circle-keyboard
|
||||||
<div class="keyboard-row">
|
*ngIf="currentLayout === 'circle'"
|
||||||
<button (click)="toggleShift()"
|
[shiftActive]="shiftActive"
|
||||||
[class.active]="shiftActive"
|
(keyPressed)="handleKeyPress($event)"
|
||||||
class="key-button shift-key">
|
(shiftToggled)="toggleShift()">
|
||||||
⇧ Shift
|
</app-circle-keyboard>
|
||||||
</button>
|
|
||||||
|
|
||||||
<button (click)="sendKey('Space')"
|
|
||||||
class="key-button space-key">
|
|
||||||
Space
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button (click)="sendKey('Backspace')"
|
|
||||||
class="key-button">
|
|
||||||
⌫ Delete
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button (click)="sendKey('Enter')"
|
|
||||||
class="key-button">
|
|
||||||
↵ Enter
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Row 5: Layout switcher -->
|
|
||||||
<div class="keyboard-row">
|
|
||||||
<button (click)="switchLayout()"
|
|
||||||
class="key-button layout-switch">
|
|
||||||
{{ currentLayout === 'qwerty' ? 'Switch to DVORAK' : 'Switch to QWERTY' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -2,62 +2,56 @@ import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
import { invoke } from "@tauri-apps/api/core";
|
||||||
|
import { QwertyKeyboardComponent } from './keyboards/qwerty-keyboard.component';
|
||||||
|
import { DvorakKeyboardComponent } from './keyboards/dvorak-keyboard.component';
|
||||||
|
import { CircleKeyboardComponent } from './keyboards/circle-keyboard.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, RouterOutlet],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterOutlet,
|
||||||
|
QwertyKeyboardComponent,
|
||||||
|
DvorakKeyboardComponent,
|
||||||
|
CircleKeyboardComponent
|
||||||
|
],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.css'
|
styleUrl: './app.component.css'
|
||||||
})
|
})
|
||||||
export class AppComponent implements AfterViewInit {
|
export class AppComponent implements AfterViewInit {
|
||||||
greetingMessage = "";
|
greetingMessage = "";
|
||||||
|
currentLayout: 'qwerty' | 'dvorak' | 'circle' = 'qwerty';
|
||||||
|
shiftActive = false;
|
||||||
|
|
||||||
@ViewChild('greetInput') inputElement!: ElementRef;
|
@ViewChild('greetInput') inputElement!: ElementRef;
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
// Beim Start fokussieren
|
|
||||||
this.inputElement.nativeElement.focus();
|
this.inputElement.nativeElement.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
greet(event: SubmitEvent, name: string): void {
|
greet(event: SubmitEvent, name: string): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
|
||||||
invoke<string>("greet", { name }).then((text) => {
|
invoke<string>("greet", { name }).then((text) => {
|
||||||
this.greetingMessage = text;
|
this.greetingMessage = text;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keyboard Layout State
|
|
||||||
currentLayout: 'qwerty' | 'dvorak' = 'qwerty';
|
|
||||||
|
|
||||||
// QWERTY Layout
|
|
||||||
qwertyRow1 = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'];
|
|
||||||
qwertyRow2 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'];
|
|
||||||
qwertyRow3 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M', ",", "."];
|
|
||||||
|
|
||||||
// DVORAK Layout
|
|
||||||
dvorakRow1 = [',', '.', 'P', 'Y', 'F', 'G', 'C', 'R', 'L'];
|
|
||||||
dvorakRow2 = ['A', 'O', 'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S'];
|
|
||||||
dvorakRow3 = ['Q', 'J', 'K', 'X', 'B', 'M', 'W', 'V', 'Z'];
|
|
||||||
|
|
||||||
shiftActive = false;
|
|
||||||
|
|
||||||
// Getters for current layout
|
|
||||||
get row1() { return this.currentLayout === 'qwerty' ? this.qwertyRow1 : this.dvorakRow1; }
|
|
||||||
get row2() { return this.currentLayout === 'qwerty' ? this.qwertyRow2 : this.dvorakRow2; }
|
|
||||||
get row3() { return this.currentLayout === 'qwerty' ? this.qwertyRow3 : this.dvorakRow3; }
|
|
||||||
|
|
||||||
toggleShift(): void {
|
toggleShift(): void {
|
||||||
this.shiftActive = !this.shiftActive;
|
this.shiftActive = !this.shiftActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
switchLayout(): void {
|
switchLayout(): void {
|
||||||
this.currentLayout = this.currentLayout === 'qwerty' ? 'dvorak' : 'qwerty';
|
if (this.currentLayout == 'qwerty'){
|
||||||
|
this.currentLayout = 'dvorak';
|
||||||
|
} else if (this.currentLayout == 'dvorak'){
|
||||||
|
this.currentLayout = 'circle';
|
||||||
|
} else if (this.currentLayout == 'circle'){
|
||||||
|
this.currentLayout = 'qwerty';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async sendKey(key: string): Promise<void> {
|
async handleKeyPress(key: string): Promise<void> {
|
||||||
this.inputElement.nativeElement.focus();
|
this.inputElement.nativeElement.focus();
|
||||||
|
|
||||||
let finalKey = key;
|
let finalKey = key;
|
||||||
|
|||||||
190
src/app/keyboards/circle-keyboard.component.ts
Normal file
190
src/app/keyboards/circle-keyboard.component.ts
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
import { Component, Output, EventEmitter, Input } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
//TODO: Second and fourth ring of keys
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-circle-keyboard',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule],
|
||||||
|
template: `
|
||||||
|
<div class="circle-keyboard-container">
|
||||||
|
<!-- Center Button - Large with 3 sections -->
|
||||||
|
<div class="center-button-container">
|
||||||
|
<!-- Top half split: Backspace left, Enter right -->
|
||||||
|
<button class="center-section top-left"
|
||||||
|
(click)="keyPressed.emit('Backspace')"
|
||||||
|
title="Backspace">
|
||||||
|
⌫
|
||||||
|
</button>
|
||||||
|
<button class="center-section top-right"
|
||||||
|
(click)="keyPressed.emit('Enter')"
|
||||||
|
title="Enter">
|
||||||
|
↵
|
||||||
|
</button>
|
||||||
|
<!-- Bottom half: Space -->
|
||||||
|
<button class="center-section bottom-right"
|
||||||
|
(click)="keyPressed.emit('Space')"
|
||||||
|
title="Space">
|
||||||
|
␣
|
||||||
|
</button>
|
||||||
|
<button (click)="shiftToggled.emit()"
|
||||||
|
[class.active]="shiftActive"
|
||||||
|
class="center-section bottom-left">
|
||||||
|
⇧
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 8 Surrounding Buttons in Circle -->
|
||||||
|
<button *ngFor="let key of circleKeysFirst; let i = index"
|
||||||
|
class="circle-button"
|
||||||
|
[style.transform]="getCirclePositionFromTop(i, 110)"
|
||||||
|
(click)="keyPressed.emit(key)">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button *ngFor="let key of circleKeysThird; let i = index"
|
||||||
|
class="circle-button third-ring"
|
||||||
|
[style.transform]="getCirclePositionFromTop(i, 170)"
|
||||||
|
(click)="keyPressed.emit(key)">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styles: [`
|
||||||
|
.circle-keyboard-container {
|
||||||
|
position: relative;
|
||||||
|
width: 400px;
|
||||||
|
height: 400px;
|
||||||
|
margin: 50px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Center Button Container */
|
||||||
|
.center-button-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Center Button Sections */
|
||||||
|
.center-section {
|
||||||
|
position: absolute;
|
||||||
|
background: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 10;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Top-left: Backspace (triangle) */
|
||||||
|
.top-left{
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
border-radius: 70px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Top-right: Enter*/
|
||||||
|
.top-right {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
border-radius: 0 70px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bottom: Space */
|
||||||
|
.bottom-left {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
border-radius: 0 0 0 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-left.active {
|
||||||
|
background: #4CAF50 !important;
|
||||||
|
color: white;
|
||||||
|
border-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-right {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
border-radius: 0 0 70px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 8 Circle Buttons */
|
||||||
|
.circle-button {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
margin: -30px 0 0 -30px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #ddd;
|
||||||
|
background: white;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.2s, border-color 0.2s;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.15);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.third-ring {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin: -20px 0 0 -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fourth-ring {
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
margin: -20px 0 0 -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-button:hover, .center-section:hover {
|
||||||
|
background: #e8e8e8;
|
||||||
|
border-color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.circle-button:active, .center-section:active {
|
||||||
|
background: #d0d0d0;
|
||||||
|
}
|
||||||
|
`]
|
||||||
|
})
|
||||||
|
export class CircleKeyboardComponent {
|
||||||
|
@Input() shiftActive = false;
|
||||||
|
@Output() keyPressed = new EventEmitter<string>();
|
||||||
|
@Output() shiftToggled = new EventEmitter<void>();
|
||||||
|
|
||||||
|
// 8 keys arranged in circle
|
||||||
|
circleKeysFirst = ['E', 'T', 'A', 'O', 'N', 'I', 'H', 'S'];
|
||||||
|
circleKeysSecond = ['R', 'L', 'D', 'U', 'C', 'M', 'W', 'Y'];
|
||||||
|
circleKeysThird = ['F', 'G', 'P', 'B', 'V', 'K', 'J', 'X'];
|
||||||
|
circleKeysFourth = ['Q', 'Z', ',', '.'];
|
||||||
|
|
||||||
|
// Calculate position for each button in circle
|
||||||
|
getCirclePositionFromTop(index: number, radius: number): string {
|
||||||
|
const angle = (index * 45) - 90; // Start from top (0°), 45° apart
|
||||||
|
const angleRad = (angle * Math.PI) / 180;
|
||||||
|
const x = Math.cos(angleRad) * radius;
|
||||||
|
const y = Math.sin(angleRad) * radius;
|
||||||
|
return `translate(${x}px, ${y}px)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
68
src/app/keyboards/dvorak-keyboard.component.ts
Normal file
68
src/app/keyboards/dvorak-keyboard.component.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { Component, Output, EventEmitter, Input } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-dvorak-keyboard',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule],
|
||||||
|
template: `
|
||||||
|
<div class="keyboard">
|
||||||
|
<div class="keyboard-row">
|
||||||
|
<button *ngFor="let key of row1"
|
||||||
|
(click)="keyPressed.emit(key)"
|
||||||
|
class="key-button">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-row">
|
||||||
|
<button *ngFor="let key of row2"
|
||||||
|
(click)="keyPressed.emit(key)"
|
||||||
|
class="key-button">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-row">
|
||||||
|
<button *ngFor="let key of row3"
|
||||||
|
(click)="keyPressed.emit(key)"
|
||||||
|
class="key-button">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-row special-keys">
|
||||||
|
<button (click)="shiftToggled.emit()"
|
||||||
|
[class.active]="shiftActive"
|
||||||
|
class="key-button shift-key">
|
||||||
|
⇧ Shift
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button (click)="keyPressed.emit('Space')"
|
||||||
|
class="key-button space-key">
|
||||||
|
Leertaste
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button (click)="keyPressed.emit('Backspace')"
|
||||||
|
class="key-button">
|
||||||
|
⌫ Delete
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button (click)="keyPressed.emit('Enter')"
|
||||||
|
class="key-button">
|
||||||
|
↵ Enter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styleUrl: '../app.component.css'
|
||||||
|
})
|
||||||
|
export class DvorakKeyboardComponent {
|
||||||
|
@Input() shiftActive = false;
|
||||||
|
@Output() keyPressed = new EventEmitter<string>();
|
||||||
|
@Output() shiftToggled = new EventEmitter<void>();
|
||||||
|
|
||||||
|
row1 = [',', '.', 'P', 'Y', 'F', 'G', 'C', 'R', 'L'];
|
||||||
|
row2 = ['A', 'O', 'E', 'U', 'I', 'D', 'H', 'T', 'N', 'S'];
|
||||||
|
row3 = ['Q', 'J', 'K', 'X', 'B', 'M', 'W', 'V', 'Z'];
|
||||||
|
}
|
||||||
68
src/app/keyboards/qwerty-keyboard.component.ts
Normal file
68
src/app/keyboards/qwerty-keyboard.component.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { Component, Output, EventEmitter, Input } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-qwerty-keyboard',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule],
|
||||||
|
template: `
|
||||||
|
<div class="keyboard">
|
||||||
|
<div class="keyboard-row">
|
||||||
|
<button *ngFor="let key of row1"
|
||||||
|
(click)="keyPressed.emit(key)"
|
||||||
|
class="key-button">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-row">
|
||||||
|
<button *ngFor="let key of row2"
|
||||||
|
(click)="keyPressed.emit(key)"
|
||||||
|
class="key-button">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-row">
|
||||||
|
<button *ngFor="let key of row3"
|
||||||
|
(click)="keyPressed.emit(key)"
|
||||||
|
class="key-button">
|
||||||
|
{{ shiftActive ? key : key.toLowerCase() }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="keyboard-row special-keys">
|
||||||
|
<button (click)="shiftToggled.emit()"
|
||||||
|
[class.active]="shiftActive"
|
||||||
|
class="key-button shift-key">
|
||||||
|
⇧ Shift
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button (click)="keyPressed.emit('Space')"
|
||||||
|
class="key-button space-key">
|
||||||
|
Leertaste
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button (click)="keyPressed.emit('Backspace')"
|
||||||
|
class="key-button">
|
||||||
|
⌫ Delete
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button (click)="keyPressed.emit('Enter')"
|
||||||
|
class="key-button">
|
||||||
|
↵ Enter
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
styleUrl: '../app.component.css'
|
||||||
|
})
|
||||||
|
export class QwertyKeyboardComponent {
|
||||||
|
@Input() shiftActive = false;
|
||||||
|
@Output() keyPressed = new EventEmitter<string>();
|
||||||
|
@Output() shiftToggled = new EventEmitter<void>();
|
||||||
|
|
||||||
|
row1 = ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P'];
|
||||||
|
row2 = ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L'];
|
||||||
|
row3 = ['Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.'];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user