Files
Tempering-Machine-Control-S…/review.txt

22739 lines
951 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

The following is a digest of the repository "copyversoin-main".
This digest is designed to be easily parsed by Large Language Models.
--- SUMMARY ---
Repository: copyversoin-main
Files Analyzed: 97
Total Text Size: 920.52 KB
Estimated Tokens (text only): ~172,519
--- DIRECTORY STRUCTURE ---
copyversoin-main/
├── codetxt/
│ ├── src/
│ │ ├── utils/
│ │ │ ├── constants.ts [binary]
│ │ │ ├── display.ts [binary]
│ │ │ ├── ignore-helper.ts [binary]
│ │ │ └── pattern-matcher.ts [binary]
│ │ ├── clone.ts [binary]
│ │ ├── index.ts [binary]
│ │ ├── ingestion.ts [binary]
│ │ ├── main.ts [binary]
│ │ ├── output-formatter.ts [binary]
│ │ ├── query-parser.ts [binary]
│ │ └── types.ts [binary]
│ ├── .npmignore
│ ├── code.txt
│ ├── package.json
│ ├── README.md
│ ├── review.txt
│ └── tsconfig.json
├── DaireApplication/
│ ├── Assets/
│ │ ├── Fonts/
│ │ │ ├── Helvetica.ttf [binary]
│ │ │ └── HLL.ttf [binary]
│ │ ├── AdminGraph.png [binary]
│ │ ├── AdminMachine.png [binary]
│ │ ├── avalonia-logo.ico [binary]
│ │ ├── bluePlug.png [binary]
│ │ ├── Board.png [binary]
│ │ ├── errorIcon.png [binary]
│ │ ├── greenPlug.png [binary]
│ │ ├── Home.png [binary]
│ │ ├── homeTrack.png [binary]
│ │ ├── icons8-green-circle-48.png [binary]
│ │ ├── icons8-red-circle-48.png [binary]
│ │ ├── LeftArrow.png [binary]
│ │ ├── LineDots.png [binary]
│ │ ├── Logo.png [binary]
│ │ ├── Machine.png [binary]
│ │ ├── Manual.png [binary]
│ │ ├── ManualControlMachine.png [binary]
│ │ ├── orangePlug.png [binary]
│ │ ├── Plus.png [binary]
│ │ ├── purplePlug.png [binary]
│ │ ├── redPlug.png [binary]
│ │ ├── RedUpArrow.png [binary]
│ │ ├── RightArrow.png [binary]
│ │ ├── Settings.png [binary]
│ │ ├── TempArrow.png [binary]
│ │ ├── TemperingGraphics.png [binary]
│ │ ├── TemperingMachine.png [binary]
│ │ ├── UpArrow.png [binary]
│ │ ├── warningIcon.png [binary]
│ │ ├── wifi.png [binary]
│ │ ├── wifioff.png [binary]
│ │ └── yellowPlug.png [binary]
│ ├── DataBase/
│ │ ├── ConfigrationTable.cs
│ │ ├── DataPathManager.cs
│ │ ├── ErrorSettingsTable.cs
│ │ ├── MachineTable.cs
│ │ ├── Mapping.cs
│ │ ├── RecipeTable.cs
│ │ ├── ScreeenTable.cs
│ │ └── UserTable.cs
│ ├── Loops/
│ │ ├── CheckInterNetLoop.cs
│ │ ├── InteractiveUILoop.cs
│ │ ├── ScreenLoop.cs
│ │ ├── serialThreadLoop.cs
│ │ └── TouchLoop.cs
│ ├── Properties/
│ │ └── PublishProfiles/
│ │ └── FolderProfile.pubxml
│ ├── ViewModels/
│ │ ├── Error.cs
│ │ ├── HoldingRegister.cs
│ │ ├── MainWindowViewModel.cs
│ │ ├── ModBusMaster.cs
│ │ ├── ViewModelBase.cs
│ │ └── X11CursorHider.cs
│ ├── Views/
│ │ ├── UserController/
│ │ │ ├── Admin.axaml
│ │ │ ├── Admin.axaml.cs
│ │ │ ├── AdvanceSettings.axaml
│ │ │ ├── AdvanceSettings.axaml.cs
│ │ │ ├── Diagnostics.axaml
│ │ │ ├── Diagnostics.axaml.cs
│ │ │ ├── Home.axaml
│ │ │ ├── Home.axaml.cs
│ │ │ ├── ManualControl.axaml
│ │ │ ├── ManualControl.axaml.cs
│ │ │ ├── Recipe.axaml
│ │ │ ├── Recipe.axaml.cs
│ │ │ ├── RecipeEdit.axaml
│ │ │ ├── RecipeEdit.axaml.cs
│ │ │ ├── Settings.axaml
│ │ │ ├── Settings.axaml.cs
│ │ │ ├── Software.axaml
│ │ │ └── Software.axaml.cs
│ │ ├── MainWindow.axaml
│ │ └── MainWindow.axaml.cs
│ ├── App.axaml
│ ├── App.axaml.cs
│ ├── app.manifest
│ ├── Program.cs
│ └── ViewLocator.cs
└── README.md
--- FILE CONTENTS ---
============================================================
FILE: codetxt/.npmignore
============================================================
# Source files (not needed in published package)
src/
*.ts
*.tsx
# Development files
.github/
.vscode/
.idea/
*.md
!README.md
# Build and development tools
tsconfig.json
.eslintrc*
.prettierrc*
jest.config.*
*.test.*
*.spec.*
# Development dependencies and scripts
package-lock.json
yarn.lock
pnpm-lock.yaml
# Git files
.git/
.gitignore
# Documentation and examples
docs/
examples/
tests/
# CI/CD files
.github/
.gitlab-ci.yml
.travis.yml
.circleci/
# Editor files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Temporary files
tmp/
temp/
*.tmp
# Logs
*.log
logs/
# Coverage reports
coverage/
*.lcov
# Environment files
.env*
!.env.example
# TypeScript declaration files (keep only the built ones)
*.d.ts
!dist/**/*.d.ts
# Source maps (optional - remove if you want to include them)
*.map
# Development scripts
scripts/
dev/
============================================================
FILE: codetxt/code.txt
============================================================
The following is a digest of the repository "codetxt".
This digest is designed to be easily parsed by Large Language Models.
--- SUMMARY ---
Repository: codetxt
Files Analyzed: 15
Total Text Size: 7.43 KB
Estimated Tokens (text only): ~2,051
--- DIRECTORY STRUCTURE ---
codetxt/
├── src/
│ ├── utils/
│ │ ├── constants.ts [binary]
│ │ ├── display.ts [binary]
│ │ ├── ignore-helper.ts [binary]
│ │ └── pattern-matcher.ts [binary]
│ ├── clone.ts [binary]
│ ├── index.ts [binary]
│ ├── ingestion.ts [binary]
│ ├── main.ts [binary]
│ ├── output-formatter.ts [binary]
│ ├── query-parser.ts [binary]
│ └── types.ts [binary]
├── .npmignore
├── package.json
├── README.md
└── tsconfig.json
--- FILE CONTENTS ---
============================================================
FILE: .npmignore
============================================================
# Source files (not needed in published package)
src/
*.ts
*.tsx
# Development files
.github/
.vscode/
.idea/
*.md
!README.md
# Build and development tools
tsconfig.json
.eslintrc*
.prettierrc*
jest.config.*
*.test.*
*.spec.*
# Development dependencies and scripts
package-lock.json
yarn.lock
pnpm-lock.yaml
# Git files
.git/
.gitignore
# Documentation and examples
docs/
examples/
tests/
# CI/CD files
.github/
.gitlab-ci.yml
.travis.yml
.circleci/
# Editor files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Temporary files
tmp/
temp/
*.tmp
# Logs
*.log
logs/
# Coverage reports
coverage/
*.lcov
# Environment files
.env*
!.env.example
# TypeScript declaration files (keep only the built ones)
*.d.ts
!dist/**/*.d.ts
# Source maps (optional - remove if you want to include them)
*.map
# Development scripts
scripts/
dev/
============================================================
FILE: package.json
============================================================
{
"name": "codetxt",
"version": "1.0.1",
"description": "CLI tool to analyze and create text dumps of codebases for LLMs. A Node.js/TypeScript implementation inspired by gitingest.",
"type": "module",
"main": "dist/index.js",
"bin": {
"codetxt": "dist/index.js"
},
"scripts": {
"start": "ts-node-esm src/index.ts",
"build": "tsc",
"prepublishOnly": "npm run build"
},
"keywords": [
"codetxt",
"cli",
"llm",
"git",
"typescript"
],
"author": "",
"license": "MIT",
"dependencies": {
"axios": "^1.7.2",
"boxen": "^8.0.1",
"build": "^0.1.4",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"figlet": "^1.8.2",
"ignore": "^7.0.5",
"inquirer": "^12.8.0",
"ora": "^8.2.0",
"simple-git": "^3.25.0",
"tiktoken": "^1.0.14"
},
"devDependencies": {
"@types/figlet": "^1.7.0",
"@types/inquirer": "^9.0.8",
"@types/node": "^20.14.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
============================================================
FILE: README.md
============================================================
# CodeTxt
A CLI tool to turn any Git repository into a prompt-friendly text ingest for LLMs.
Whether you're preparing codebases for AI analysis, training data, or static search indexing, CodeTxt helps you generate clean, filtered code dumps with ease.
## Installation
### Prerequisites
First, ensure you have Node.js (v18 or higher) installed on your system.
### Global Installation
You can install the CLI globally in one of two ways:
#### Option 1: Install from local project
```bash
# After cloning the repository
npm install -g .
```
This command needs to be run from the root of the project. It will build the TypeScript code and link the `codetxt` command to your system.
#### Option 2: Install from npm registry (when published)
```bash
npm install -g codetxt
```
After installation, you can use the `codetxt` command from anywhere in your terminal.
## Usage
The CLI is simple to use. You can point it to a remote Git repository or a local directory.
### From a Remote URL
```bash
codetxt https://github.com/facebook/react
```
### From a Local Directory
```bash
# Analyze the current directory
codetxt .
# Analyze a specific local path
codetxt /path/to/my/project
```
## Options
| Flag | Alias | Description | Default |
| --------------------------- | ----- | --------------------------------------------------------------------------- | ------------ |
| `--output <file>` | `-o` | Specify an output file. Use `-` for stdout. | `code.txt` |
| `--max-size <bytes>` | `-s` | Skip files larger than this size in bytes. | `10MB` |
| `--branch <name>` | `-b` | For remote repos, specify a branch to clone. | Default repo branch |
| `--include-pattern <glob>` | | Only include files/directories matching the glob pattern(s). | - |
| `--exclude-pattern <glob>` | | Exclude files/directories matching the glob pattern(s). | - |
| `--include-gitignored` | | Process files and directories that are normally ignored by `.gitignore`. | `false` |
| `--force` | `-f` | Overwrite an existing output file without asking for confirmation. | `false` |
| `--token <pat>` | `-t` | GitHub Personal Access Token for private repositories. | - |
## Examples
### Basic Usage
**Write to a specific file:**
```bash
codetxt https://github.com/expressjs/express -o express-code.txt
```
**Pipe output to another command (e.g., `grep`):**
```bash
codetxt . -o - | grep "function"
```
**Analyze a specific branch and ignore large files:**
```bash
codetxt https://github.com/vuejs/core --branch main --max-size 50000
```
**Include files normally ignored by .gitignore:**
```bash
codetxt . --include-gitignored -o all-files.txt
```
### Advanced Pattern Filtering
The tool supports powerful glob-style pattern filtering for fine-grained control over which files to include or exclude. This is especially useful for monorepos or workspaces with multiple projects.
#### Exclude Patterns (`--exclude-pattern`)
Use this to skip specific files or entire directories.
**Exclude a specific directory (e.g., `docs/`):**
```bash
codetxt . --exclude-pattern "docs/"
```
*Result: Will analyze the entire project but skip the `docs` directory and all its contents.*
**Exclude multiple directories and file types:**
```bash
codetxt . --exclude-pattern "project-A/" --exclude-pattern "tests/" --exclude-pattern "*.log"
```
*Result: Will skip `project-A`, the `tests` directory, and any file ending with `.log`.*
#### Include Patterns (`--include-pattern`)
Use this to create a "whitelist" of what you want to analyze. Everything else will be ignored.
**Include only a specific directory and its contents:**
```bash
codetxt . --include-pattern "project-A/**"
```
*Result: Will analyze **only** the contents of `project-A`. All other files and directories will be ignored.*
**Include only JavaScript and Markdown files from the entire project:**
```bash
codetxt . --include-pattern "**/*.js" --include-pattern "**/*.md"
```
*Result: The digest will only contain JavaScript and Markdown files.*
#### Important Notes on Include Logic
When using `--include-pattern`, the tool assumes you want **nothing except** what matches the pattern:
- **For files**: The filename must match the pattern to be included.
- **For directories**: The tool will traverse all directories, but only those containing files that match the include pattern will appear in the final output tree.
This gives you complete control over what gets analyzed, which is perfect for focusing on specific parts of a large codebase.
## How to Set Up for Development
1. Clone this repository.
2. Install dependencies: `npm install`
3. Build the project: `npm run build`
4. Run directly using `ts-node`: `npm start .`
============================================================
FILE: tsconfig.json
============================================================
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
============================================================
FILE: codetxt/package.json
============================================================
{
"name": "codetxt",
"version": "1.0.1",
"description": "CLI tool to analyze and create text dumps of codebases for LLMs. A Node.js/TypeScript implementation inspired by gitingest.",
"type": "module",
"main": "dist/index.js",
"bin": {
"codetxt": "dist/index.js"
},
"scripts": {
"start": "ts-node-esm src/index.ts",
"build": "tsc",
"prepublishOnly": "npm run build"
},
"keywords": [
"codetxt",
"cli",
"llm",
"git",
"typescript"
],
"author": "",
"license": "MIT",
"dependencies": {
"axios": "^1.7.2",
"boxen": "^8.0.1",
"build": "^0.1.4",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"figlet": "^1.8.2",
"ignore": "^7.0.5",
"inquirer": "^12.8.0",
"ora": "^8.2.0",
"simple-git": "^3.25.0",
"tiktoken": "^1.0.14"
},
"devDependencies": {
"@types/figlet": "^1.7.0",
"@types/inquirer": "^9.0.8",
"@types/node": "^20.14.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
============================================================
FILE: codetxt/README.md
============================================================
# CodeTxt
A CLI tool to turn any Git repository into a prompt-friendly text ingest for LLMs.
Whether you're preparing codebases for AI analysis, training data, or static search indexing, CodeTxt helps you generate clean, filtered code dumps with ease.
## Installation
### Prerequisites
First, ensure you have Node.js (v18 or higher) installed on your system.
### Global Installation
You can install the CLI globally in one of two ways:
#### Option 1: Install from local project
```bash
# After cloning the repository
npm install -g .
```
This command needs to be run from the root of the project. It will build the TypeScript code and link the `codetxt` command to your system.
#### Option 2: Install from npm registry (when published)
```bash
npm install -g codetxt
```
After installation, you can use the `codetxt` command from anywhere in your terminal.
## Usage
The CLI is simple to use. You can point it to a remote Git repository or a local directory.
### From a Remote URL
```bash
codetxt https://github.com/facebook/react
```
### From a Local Directory
```bash
# Analyze the current directory
codetxt .
# Analyze a specific local path
codetxt /path/to/my/project
```
## Options
| Flag | Alias | Description | Default |
| --------------------------- | ----- | --------------------------------------------------------------------------- | ------------ |
| `--output <file>` | `-o` | Specify an output file. Use `-` for stdout. | `code.txt` |
| `--max-size <bytes>` | `-s` | Skip files larger than this size in bytes. | `10MB` |
| `--branch <name>` | `-b` | For remote repos, specify a branch to clone. | Default repo branch |
| `--include-pattern <glob>` | | Only include files/directories matching the glob pattern(s). | - |
| `--exclude-pattern <glob>` | | Exclude files/directories matching the glob pattern(s). | - |
| `--include-gitignored` | | Process files and directories that are normally ignored by `.gitignore`. | `false` |
| `--force` | `-f` | Overwrite an existing output file without asking for confirmation. | `false` |
| `--token <pat>` | `-t` | GitHub Personal Access Token for private repositories. | - |
## Examples
### Basic Usage
**Write to a specific file:**
```bash
codetxt https://github.com/expressjs/express -o express-code.txt
```
**Pipe output to another command (e.g., `grep`):**
```bash
codetxt . -o - | grep "function"
```
**Analyze a specific branch and ignore large files:**
```bash
codetxt https://github.com/vuejs/core --branch main --max-size 50000
```
**Include files normally ignored by .gitignore:**
```bash
codetxt . --include-gitignored -o all-files.txt
```
### Advanced Pattern Filtering
The tool supports powerful glob-style pattern filtering for fine-grained control over which files to include or exclude. This is especially useful for monorepos or workspaces with multiple projects.
#### Exclude Patterns (`--exclude-pattern`)
Use this to skip specific files or entire directories.
**Exclude a specific directory (e.g., `docs/`):**
```bash
codetxt . --exclude-pattern "docs/"
```
*Result: Will analyze the entire project but skip the `docs` directory and all its contents.*
**Exclude multiple directories and file types:**
```bash
codetxt . --exclude-pattern "project-A/" --exclude-pattern "tests/" --exclude-pattern "*.log"
```
*Result: Will skip `project-A`, the `tests` directory, and any file ending with `.log`.*
#### Include Patterns (`--include-pattern`)
Use this to create a "whitelist" of what you want to analyze. Everything else will be ignored.
**Include only a specific directory and its contents:**
```bash
codetxt . --include-pattern "project-A/**"
```
*Result: Will analyze **only** the contents of `project-A`. All other files and directories will be ignored.*
**Include only JavaScript and Markdown files from the entire project:**
```bash
codetxt . --include-pattern "**/*.js" --include-pattern "**/*.md"
```
*Result: The digest will only contain JavaScript and Markdown files.*
#### Important Notes on Include Logic
When using `--include-pattern`, the tool assumes you want **nothing except** what matches the pattern:
- **For files**: The filename must match the pattern to be included.
- **For directories**: The tool will traverse all directories, but only those containing files that match the include pattern will appear in the final output tree.
This gives you complete control over what gets analyzed, which is perfect for focusing on specific parts of a large codebase.
## How to Set Up for Development
1. Clone this repository.
2. Install dependencies: `npm install`
3. Build the project: `npm run build`
4. Run directly using `ts-node`: `npm start .`
============================================================
FILE: codetxt/review.txt
============================================================
The following is a digest of the repository "codetxt".
This digest is designed to be easily parsed by Large Language Models.
--- SUMMARY ---
Repository: codetxt
Files Analyzed: 16
Total Text Size: 16.26 KB
Estimated Tokens (text only): ~4,183
--- DIRECTORY STRUCTURE ---
codetxt/
├── src/
│ ├── utils/
│ │ ├── constants.ts [binary]
│ │ ├── display.ts [binary]
│ │ ├── ignore-helper.ts [binary]
│ │ └── pattern-matcher.ts [binary]
│ ├── clone.ts [binary]
│ ├── index.ts [binary]
│ ├── ingestion.ts [binary]
│ ├── main.ts [binary]
│ ├── output-formatter.ts [binary]
│ ├── query-parser.ts [binary]
│ └── types.ts [binary]
├── .npmignore
├── code.txt
├── package.json
├── README.md
└── tsconfig.json
--- FILE CONTENTS ---
============================================================
FILE: .npmignore
============================================================
# Source files (not needed in published package)
src/
*.ts
*.tsx
# Development files
.github/
.vscode/
.idea/
*.md
!README.md
# Build and development tools
tsconfig.json
.eslintrc*
.prettierrc*
jest.config.*
*.test.*
*.spec.*
# Development dependencies and scripts
package-lock.json
yarn.lock
pnpm-lock.yaml
# Git files
.git/
.gitignore
# Documentation and examples
docs/
examples/
tests/
# CI/CD files
.github/
.gitlab-ci.yml
.travis.yml
.circleci/
# Editor files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Temporary files
tmp/
temp/
*.tmp
# Logs
*.log
logs/
# Coverage reports
coverage/
*.lcov
# Environment files
.env*
!.env.example
# TypeScript declaration files (keep only the built ones)
*.d.ts
!dist/**/*.d.ts
# Source maps (optional - remove if you want to include them)
*.map
# Development scripts
scripts/
dev/
============================================================
FILE: code.txt
============================================================
The following is a digest of the repository "codetxt".
This digest is designed to be easily parsed by Large Language Models.
--- SUMMARY ---
Repository: codetxt
Files Analyzed: 15
Total Text Size: 7.43 KB
Estimated Tokens (text only): ~2,051
--- DIRECTORY STRUCTURE ---
codetxt/
├── src/
│ ├── utils/
│ │ ├── constants.ts [binary]
│ │ ├── display.ts [binary]
│ │ ├── ignore-helper.ts [binary]
│ │ └── pattern-matcher.ts [binary]
│ ├── clone.ts [binary]
│ ├── index.ts [binary]
│ ├── ingestion.ts [binary]
│ ├── main.ts [binary]
│ ├── output-formatter.ts [binary]
│ ├── query-parser.ts [binary]
│ └── types.ts [binary]
├── .npmignore
├── package.json
├── README.md
└── tsconfig.json
--- FILE CONTENTS ---
============================================================
FILE: .npmignore
============================================================
# Source files (not needed in published package)
src/
*.ts
*.tsx
# Development files
.github/
.vscode/
.idea/
*.md
!README.md
# Build and development tools
tsconfig.json
.eslintrc*
.prettierrc*
jest.config.*
*.test.*
*.spec.*
# Development dependencies and scripts
package-lock.json
yarn.lock
pnpm-lock.yaml
# Git files
.git/
.gitignore
# Documentation and examples
docs/
examples/
tests/
# CI/CD files
.github/
.gitlab-ci.yml
.travis.yml
.circleci/
# Editor files
.vscode/
.idea/
*.swp
*.swo
# OS files
.DS_Store
Thumbs.db
# Temporary files
tmp/
temp/
*.tmp
# Logs
*.log
logs/
# Coverage reports
coverage/
*.lcov
# Environment files
.env*
!.env.example
# TypeScript declaration files (keep only the built ones)
*.d.ts
!dist/**/*.d.ts
# Source maps (optional - remove if you want to include them)
*.map
# Development scripts
scripts/
dev/
============================================================
FILE: package.json
============================================================
{
"name": "codetxt",
"version": "1.0.1",
"description": "CLI tool to analyze and create text dumps of codebases for LLMs. A Node.js/TypeScript implementation inspired by gitingest.",
"type": "module",
"main": "dist/index.js",
"bin": {
"codetxt": "dist/index.js"
},
"scripts": {
"start": "ts-node-esm src/index.ts",
"build": "tsc",
"prepublishOnly": "npm run build"
},
"keywords": [
"codetxt",
"cli",
"llm",
"git",
"typescript"
],
"author": "",
"license": "MIT",
"dependencies": {
"axios": "^1.7.2",
"boxen": "^8.0.1",
"build": "^0.1.4",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"figlet": "^1.8.2",
"ignore": "^7.0.5",
"inquirer": "^12.8.0",
"ora": "^8.2.0",
"simple-git": "^3.25.0",
"tiktoken": "^1.0.14"
},
"devDependencies": {
"@types/figlet": "^1.7.0",
"@types/inquirer": "^9.0.8",
"@types/node": "^20.14.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
============================================================
FILE: README.md
============================================================
# CodeTxt
A CLI tool to turn any Git repository into a prompt-friendly text ingest for LLMs.
Whether you're preparing codebases for AI analysis, training data, or static search indexing, CodeTxt helps you generate clean, filtered code dumps with ease.
## Installation
### Prerequisites
First, ensure you have Node.js (v18 or higher) installed on your system.
### Global Installation
You can install the CLI globally in one of two ways:
#### Option 1: Install from local project
```bash
# After cloning the repository
npm install -g .
```
This command needs to be run from the root of the project. It will build the TypeScript code and link the `codetxt` command to your system.
#### Option 2: Install from npm registry (when published)
```bash
npm install -g codetxt
```
After installation, you can use the `codetxt` command from anywhere in your terminal.
## Usage
The CLI is simple to use. You can point it to a remote Git repository or a local directory.
### From a Remote URL
```bash
codetxt https://github.com/facebook/react
```
### From a Local Directory
```bash
# Analyze the current directory
codetxt .
# Analyze a specific local path
codetxt /path/to/my/project
```
## Options
| Flag | Alias | Description | Default |
| --------------------------- | ----- | --------------------------------------------------------------------------- | ------------ |
| `--output <file>` | `-o` | Specify an output file. Use `-` for stdout. | `code.txt` |
| `--max-size <bytes>` | `-s` | Skip files larger than this size in bytes. | `10MB` |
| `--branch <name>` | `-b` | For remote repos, specify a branch to clone. | Default repo branch |
| `--include-pattern <glob>` | | Only include files/directories matching the glob pattern(s). | - |
| `--exclude-pattern <glob>` | | Exclude files/directories matching the glob pattern(s). | - |
| `--include-gitignored` | | Process files and directories that are normally ignored by `.gitignore`. | `false` |
| `--force` | `-f` | Overwrite an existing output file without asking for confirmation. | `false` |
| `--token <pat>` | `-t` | GitHub Personal Access Token for private repositories. | - |
## Examples
### Basic Usage
**Write to a specific file:**
```bash
codetxt https://github.com/expressjs/express -o express-code.txt
```
**Pipe output to another command (e.g., `grep`):**
```bash
codetxt . -o - | grep "function"
```
**Analyze a specific branch and ignore large files:**
```bash
codetxt https://github.com/vuejs/core --branch main --max-size 50000
```
**Include files normally ignored by .gitignore:**
```bash
codetxt . --include-gitignored -o all-files.txt
```
### Advanced Pattern Filtering
The tool supports powerful glob-style pattern filtering for fine-grained control over which files to include or exclude. This is especially useful for monorepos or workspaces with multiple projects.
#### Exclude Patterns (`--exclude-pattern`)
Use this to skip specific files or entire directories.
**Exclude a specific directory (e.g., `docs/`):**
```bash
codetxt . --exclude-pattern "docs/"
```
*Result: Will analyze the entire project but skip the `docs` directory and all its contents.*
**Exclude multiple directories and file types:**
```bash
codetxt . --exclude-pattern "project-A/" --exclude-pattern "tests/" --exclude-pattern "*.log"
```
*Result: Will skip `project-A`, the `tests` directory, and any file ending with `.log`.*
#### Include Patterns (`--include-pattern`)
Use this to create a "whitelist" of what you want to analyze. Everything else will be ignored.
**Include only a specific directory and its contents:**
```bash
codetxt . --include-pattern "project-A/**"
```
*Result: Will analyze **only** the contents of `project-A`. All other files and directories will be ignored.*
**Include only JavaScript and Markdown files from the entire project:**
```bash
codetxt . --include-pattern "**/*.js" --include-pattern "**/*.md"
```
*Result: The digest will only contain JavaScript and Markdown files.*
#### Important Notes on Include Logic
When using `--include-pattern`, the tool assumes you want **nothing except** what matches the pattern:
- **For files**: The filename must match the pattern to be included.
- **For directories**: The tool will traverse all directories, but only those containing files that match the include pattern will appear in the final output tree.
This gives you complete control over what gets analyzed, which is perfect for focusing on specific parts of a large codebase.
## How to Set Up for Development
1. Clone this repository.
2. Install dependencies: `npm install`
3. Build the project: `npm run build`
4. Run directly using `ts-node`: `npm start .`
============================================================
FILE: tsconfig.json
============================================================
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
============================================================
FILE: package.json
============================================================
{
"name": "codetxt",
"version": "1.0.1",
"description": "CLI tool to analyze and create text dumps of codebases for LLMs. A Node.js/TypeScript implementation inspired by gitingest.",
"type": "module",
"main": "dist/index.js",
"bin": {
"codetxt": "dist/index.js"
},
"scripts": {
"start": "ts-node-esm src/index.ts",
"build": "tsc",
"prepublishOnly": "npm run build"
},
"keywords": [
"codetxt",
"cli",
"llm",
"git",
"typescript"
],
"author": "",
"license": "MIT",
"dependencies": {
"axios": "^1.7.2",
"boxen": "^8.0.1",
"build": "^0.1.4",
"chalk": "^5.3.0",
"commander": "^12.1.0",
"figlet": "^1.8.2",
"ignore": "^7.0.5",
"inquirer": "^12.8.0",
"ora": "^8.2.0",
"simple-git": "^3.25.0",
"tiktoken": "^1.0.14"
},
"devDependencies": {
"@types/figlet": "^1.7.0",
"@types/inquirer": "^9.0.8",
"@types/node": "^20.14.2",
"ts-node": "^10.9.2",
"typescript": "^5.4.5"
}
}
============================================================
FILE: README.md
============================================================
# CodeTxt
A CLI tool to turn any Git repository into a prompt-friendly text ingest for LLMs.
Whether you're preparing codebases for AI analysis, training data, or static search indexing, CodeTxt helps you generate clean, filtered code dumps with ease.
## Installation
### Prerequisites
First, ensure you have Node.js (v18 or higher) installed on your system.
### Global Installation
You can install the CLI globally in one of two ways:
#### Option 1: Install from local project
```bash
# After cloning the repository
npm install -g .
```
This command needs to be run from the root of the project. It will build the TypeScript code and link the `codetxt` command to your system.
#### Option 2: Install from npm registry (when published)
```bash
npm install -g codetxt
```
After installation, you can use the `codetxt` command from anywhere in your terminal.
## Usage
The CLI is simple to use. You can point it to a remote Git repository or a local directory.
### From a Remote URL
```bash
codetxt https://github.com/facebook/react
```
### From a Local Directory
```bash
# Analyze the current directory
codetxt .
# Analyze a specific local path
codetxt /path/to/my/project
```
## Options
| Flag | Alias | Description | Default |
| --------------------------- | ----- | --------------------------------------------------------------------------- | ------------ |
| `--output <file>` | `-o` | Specify an output file. Use `-` for stdout. | `code.txt` |
| `--max-size <bytes>` | `-s` | Skip files larger than this size in bytes. | `10MB` |
| `--branch <name>` | `-b` | For remote repos, specify a branch to clone. | Default repo branch |
| `--include-pattern <glob>` | | Only include files/directories matching the glob pattern(s). | - |
| `--exclude-pattern <glob>` | | Exclude files/directories matching the glob pattern(s). | - |
| `--include-gitignored` | | Process files and directories that are normally ignored by `.gitignore`. | `false` |
| `--force` | `-f` | Overwrite an existing output file without asking for confirmation. | `false` |
| `--token <pat>` | `-t` | GitHub Personal Access Token for private repositories. | - |
## Examples
### Basic Usage
**Write to a specific file:**
```bash
codetxt https://github.com/expressjs/express -o express-code.txt
```
**Pipe output to another command (e.g., `grep`):**
```bash
codetxt . -o - | grep "function"
```
**Analyze a specific branch and ignore large files:**
```bash
codetxt https://github.com/vuejs/core --branch main --max-size 50000
```
**Include files normally ignored by .gitignore:**
```bash
codetxt . --include-gitignored -o all-files.txt
```
### Advanced Pattern Filtering
The tool supports powerful glob-style pattern filtering for fine-grained control over which files to include or exclude. This is especially useful for monorepos or workspaces with multiple projects.
#### Exclude Patterns (`--exclude-pattern`)
Use this to skip specific files or entire directories.
**Exclude a specific directory (e.g., `docs/`):**
```bash
codetxt . --exclude-pattern "docs/"
```
*Result: Will analyze the entire project but skip the `docs` directory and all its contents.*
**Exclude multiple directories and file types:**
```bash
codetxt . --exclude-pattern "project-A/" --exclude-pattern "tests/" --exclude-pattern "*.log"
```
*Result: Will skip `project-A`, the `tests` directory, and any file ending with `.log`.*
#### Include Patterns (`--include-pattern`)
Use this to create a "whitelist" of what you want to analyze. Everything else will be ignored.
**Include only a specific directory and its contents:**
```bash
codetxt . --include-pattern "project-A/**"
```
*Result: Will analyze **only** the contents of `project-A`. All other files and directories will be ignored.*
**Include only JavaScript and Markdown files from the entire project:**
```bash
codetxt . --include-pattern "**/*.js" --include-pattern "**/*.md"
```
*Result: The digest will only contain JavaScript and Markdown files.*
#### Important Notes on Include Logic
When using `--include-pattern`, the tool assumes you want **nothing except** what matches the pattern:
- **For files**: The filename must match the pattern to be included.
- **For directories**: The tool will traverse all directories, but only those containing files that match the include pattern will appear in the final output tree.
This gives you complete control over what gets analyzed, which is perfect for focusing on specific parts of a large codebase.
## How to Set Up for Development
1. Clone this repository.
2. Install dependencies: `npm install`
3. Build the project: `npm run build`
4. Run directly using `ts-node`: `npm start .`
============================================================
FILE: tsconfig.json
============================================================
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
============================================================
FILE: codetxt/tsconfig.json
============================================================
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
============================================================
FILE: DaireApplication/DataBase/ConfigrationTable.cs
============================================================
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
namespace DaireApplication.DataBase;
public class ConfigrationTable
{
public int Id { get; set; }
public int Max { get; set; } = 0;
public int Min { get; set; } = 0;
public List<int> H_out { get; set; } = new();
public List<int> FC_out { get; set; } = new();
public List<int> SC_out { get; set; } = new();
public int kp { get; set; } = 0;
public int ki { get; set; } = 0;
public int kd { get; set; } = 0;
public int kl { get; set; } = 0;
public string name { get; set; } = "";
public float i_neut { get; set; } = 0;
public float i_mot1 { get; set; } = 0;
public float i_mot2 { get; set; } = 0;
public float FC_Threshold { get; set; } = 3;
public float HeatConRange { get; set; } = 50;
public List<ConfigrationTable> ReadConfigrations()
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
List<ConfigrationTable> configrations = new List<ConfigrationTable>();
if (File.Exists(filePath))
{
using StreamReader reader = new(filePath);
string header = reader.ReadLine();
while (!reader.EndOfStream)
{
string[] columns = reader.ReadLine().Split(',');
configrations.Add(new ConfigrationTable
{
Id = int.Parse(columns[0]),
Max = int.Parse(columns[1]),
Min = int.Parse(columns[2]),
H_out = columns[3].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(),
FC_out = columns[4].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(),
SC_out = columns[5].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(),
kp = int.Parse(columns[6]),
ki = int.Parse(columns[7]),
kd = int.Parse(columns[8]),
kl = int.Parse(columns[9]),
name=columns[10],
i_neut= float.Parse(columns[11]),
i_mot1= float.Parse(columns[12]),
i_mot2= float.Parse(columns[13]),
FC_Threshold = float.Parse(columns[14]),
HeatConRange = float.Parse(columns[15]),
});
}
return configrations;
}
return null;
}
public int GetMaxId()
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
if (File.Exists(filePath))
{
return File.ReadAllLines(filePath)
.Select(line => line.Split(','))
.Where(columns => columns.Length > 0)
.Select(columns => int.TryParse(columns[0], out int id) ? id : 0)
.Max();
}
return -1;
}
public ConfigrationTable ReadConfigrationById(string id)
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
if (File.Exists(filePath))
{
foreach (var line in File.ReadLines(filePath))
{
string[] columns = line.Split(',');
if (columns[0] == id)
{
return new ConfigrationTable
{
Id = int.Parse(columns[0]),
Max = int.Parse(columns[1]),
Min = int.Parse(columns[2]),
H_out = columns[3].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(),
FC_out = columns[4].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(),
SC_out = columns[5].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(),
kp = int.Parse(columns[6]),
ki = int.Parse(columns[7]),
kd = int.Parse(columns[8]),
kl = int.Parse(columns[9]),
name=columns[10],
i_neut = float.Parse(columns[11]),
i_mot1 = float.Parse(columns[12]),
i_mot2 = float.Parse(columns[13]),
FC_Threshold = float.Parse(columns[14]),
HeatConRange = float.Parse(columns[15]),
};
}
}
}
return null;
}
public bool AddConfigration(ConfigrationTable data)
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
if (File.Exists(filePath))
{
string newEntry = string.Join(",", [
GetMaxId() + 1,
data.Max,
data.Min,
string.Join("|", data.H_out),
string.Join("|", data.FC_out),
string.Join("|", data.SC_out),
data.kp,
data.ki,
data.kd,
data.kl,
data.name,
data.i_neut,
data.i_mot1,
data.i_mot2,
data.FC_Threshold,
data.HeatConRange
]);
File.AppendAllText(filePath, newEntry + Environment.NewLine);
return true;
}
return false;
}
public bool DeleteConfigration(string id)
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
if (File.Exists(filePath))
{
var filteredLines = File.ReadLines(filePath).Where(line => !line.StartsWith(id + ",")).ToArray();
File.WriteAllLines(filePath, filteredLines);
return true;
}
return false;
}
public bool UpdateConfigration(ConfigrationTable updatedConfig)
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
bool configFound = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (columns.Length < 10)
continue;
if (int.Parse(columns[0]) == updatedConfig.Id)
{
columns[1] = updatedConfig.Max.ToString();
columns[2] = updatedConfig.Min.ToString();
columns[3] = string.Join("|", updatedConfig.H_out);
columns[4] = string.Join("|", updatedConfig.FC_out);
columns[5] = string.Join("|", updatedConfig.SC_out);
columns[6] = updatedConfig.kp.ToString();
columns[7] = updatedConfig.ki.ToString();
columns[8] = updatedConfig.kd.ToString();
columns[9] = updatedConfig.kl.ToString();
columns[10] = updatedConfig.name;
columns[11] = updatedConfig.i_neut.ToString(CultureInfo.InvariantCulture);
columns[12] = updatedConfig.i_mot1.ToString(CultureInfo.InvariantCulture);
columns[13] = updatedConfig.i_mot2.ToString(CultureInfo.InvariantCulture);
columns[14] = updatedConfig.FC_Threshold.ToString(CultureInfo.InvariantCulture);
columns[15] = updatedConfig.HeatConRange.ToString(CultureInfo.InvariantCulture);
lines[i] = string.Join(",", columns);
configFound = true;
break;
}
}
if (configFound)
{
File.WriteAllLines(filePath, lines);
return true;
}
}
return false;
}
}
============================================================
FILE: DaireApplication/DataBase/DataPathManager.cs
============================================================
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Collections.Generic;
namespace DaireApplication.DataBase
{
public static class DataPathManager
{
private static readonly string AppName = "DaireApplication";
private static string _dataDirectory;
// Expected CSV headers for each file
private static readonly string UsersCsvHeader = "ID,UserName,Password,CanEdit,IsAdmin,IsActive";
private static readonly string RecipeCsvHeader = "ID,Name,TankTemp,FountainTemp,Mixer,Fountain,MoldHeater,Vibration,VibHeater,Pedal,PedalOnTime,PedalOffTime,HeatingGoal,CoolingGoal,PouringGoal";
private static readonly string MachineCsvHeader = "ID,TankMaxHeat,PumbMaxHeat,PumbDelay,MixerDelay,HeatingDelay,CoolingDelay,PouringDelay,PumbMinHeat,AbsMaxTemp,AbsMinTemp,PreHeatingTemp,SetTemp1,SetTemp2,SetTemp3,SetTemp4";
private static readonly string MappingCsvHeader = "Id,Name,Address,IsRead,BitNumbers";
private static readonly string ConfigrationCsvHeader = "Id,Max,Min,H_out,FC_out,SC_out,kp,ki,kd,kl,Name,I_Nuet,I_Mot1,I_Mot2,FC_Threshold,HeatConRange";
private static readonly string ErrorSettingsCsvHeader = "Id,gridFreq,phaseNumber,extPower,phaseVoltage";
private static readonly string ScreenCsvHeader = "Id,Brightness,DimSec,OffSec,Port,BoundRate,Parity,StopBits,SendingTime,WarningLimit,ErrorLimit";
static DataPathManager()
{
try
{
// Determine the data directory based on the OS
if (OperatingSystem.IsWindows())
{
// Windows: Use LocalApplicationData
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
_dataDirectory = Path.Combine(appDataPath, AppName);
}
else
{
// Linux/macOS: Use ~/.local/share/DaireApplication
string home = Environment.GetEnvironmentVariable("HOME") ?? "/tmp";
_dataDirectory = Path.Combine(home, ".local", "share", AppName);
}
// Ensure the directory exists
Directory.CreateDirectory(_dataDirectory);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to CreateDirectory: {ex.Message}");
Console.WriteLine($"_dataDirectory: {_dataDirectory}");
}
}
/// <summary>
/// Returns the full path for a data file, ensuring the directory exists.
/// </summary>
public static string GetDataFilePath(string fileName)
{
try
{
// Ensure the directory exists before returning the file path
Directory.CreateDirectory(_dataDirectory);
return Path.Combine(_dataDirectory, fileName);
}
catch (Exception ex)
{
Console.WriteLine($"Failed to GetDataFilePath: {ex.Message}");
return string.Empty;
}
}
/// <summary>
/// Migrates legacy data files from the application's base directory to the new data directory.
/// </summary>
public static void MigrateLegacyData()
{
try
{
string[] csvFiles = { "Users.csv", "Recipe.csv", "Machine.csv", "Mapping.csv",
"Configration.csv", "ErrorSettings.csv", "Screen.csv" };
foreach (string file in csvFiles)
{
string legacyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file);
string newPath = GetDataFilePath(file);
// If the file exists in the old location but not in the new location, move it
if (File.Exists(legacyPath) && !File.Exists(newPath))
{
// Ensure the target directory exists
Directory.CreateDirectory(Path.GetDirectoryName(newPath) ?? _dataDirectory);
File.Move(legacyPath, newPath);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Failed to MigrateLegacyData: {ex.Message}");
}
}
/// <summary>
/// Migrates CSV files by adding missing columns with default values instead of deleting them.
/// </summary>
public static void MigrateCsvFiles()
{
MigrateCsvFile("Users.csv", UsersCsvHeader, GetUsersDefaultValues);
MigrateCsvFile("Recipe.csv", RecipeCsvHeader, GetRecipeDefaultValues);
MigrateCsvFile("Machine.csv", MachineCsvHeader, GetMachineDefaultValues);
MigrateCsvFile("Mapping.csv", MappingCsvHeader, GetMappingDefaultValues);
MigrateCsvFile("Configration.csv", ConfigrationCsvHeader, GetConfigrationDefaultValues);
MigrateCsvFile("ErrorSettings.csv", ErrorSettingsCsvHeader, GetErrorSettingsDefaultValues);
MigrateCsvFile("Screen.csv", ScreenCsvHeader, GetScreenDefaultValues);
}
/// <summary>
/// Migrates a CSV file by adding missing columns with default values.
/// </summary>
private static void MigrateCsvFile(string fileName, string expectedHeader, Func<string, string> getDefaultValue)
{
try
{
string filePath = GetDataFilePath(fileName);
if (!File.Exists(filePath))
return;
string[] lines = File.ReadAllLines(filePath);
if (lines.Length == 0)
return;
string actualHeader = lines[0];
if (string.Equals(actualHeader.Trim(), expectedHeader.Trim(), StringComparison.OrdinalIgnoreCase))
return; // No migration needed
string[] expectedColumns = expectedHeader.Split(',');
string[] actualColumns = actualHeader.Split(',');
// Find missing columns
var missingColumns = new List<(int index, string columnName)>();
for (int i = 0; i < expectedColumns.Length; i++)
{
if (i >= actualColumns.Length || !string.Equals(actualColumns[i].Trim(), expectedColumns[i].Trim(), StringComparison.OrdinalIgnoreCase))
{
missingColumns.Add((i, expectedColumns[i]));
}
}
if (missingColumns.Count == 0)
return;
// Migrate the file
var migratedLines = new List<string>();
// Add new header
migratedLines.Add(expectedHeader);
// Migrate data rows
for (int i = 1; i < lines.Length; i++)
{
string[] dataColumns = lines[i].Split(',');
var newDataColumns = new List<string>(dataColumns);
// Add missing columns with default values
foreach (var missing in missingColumns)
{
if (missing.index >= newDataColumns.Count)
{
newDataColumns.Add(getDefaultValue(missing.columnName));
}
else
{
newDataColumns.Insert(missing.index, getDefaultValue(missing.columnName));
}
}
migratedLines.Add(string.Join(",", newDataColumns));
}
// Write the migrated file
File.WriteAllLines(filePath, migratedLines);
Console.WriteLine($"Migrated {fileName} - added {missingColumns.Count} missing columns");
}
catch (Exception ex)
{
Console.WriteLine($"Failed to migrate {fileName}: {ex.Message}");
}
}
// Default value providers for each file type
private static string GetUsersDefaultValues(string columnName)
{
return columnName switch
{
"IsActive" => "0",
_ => ""
};
}
private static string GetRecipeDefaultValues(string columnName)
{
return columnName switch
{
"TankTemp" => "0",
"FountainTemp" => "0",
"Mixer" => "0",
"Fountain" => "0",
"MoldHeater" => "0",
"Vibration" => "0",
"VibHeater" => "0",
"Pedal" => "0",
"PedalOnTime" => "0",
"PedalOffTime" => "0",
"HeatingGoal" => "46",
"CoolingGoal" => "27",
"PouringGoal" => "30",
_ => ""
};
}
private static string GetMachineDefaultValues(string columnName)
{
return columnName switch
{
"TankMaxHeat" => "50",
"PumbMaxHeat" => "50",
"PumbDelay" => "60",
"MixerDelay" => "60",
"HeatingDelay" => "60",
"CoolingDelay" => "60",
"PouringDelay" => "60",
"PumbMinHeat" => "-10",
"AbsMaxTemp" => "65",
"AbsMinTemp" => "-14",
"PreHeatingTemp" => "5",
"SetTemp1" => "0",
"SetTemp2" => "-10",
"SetTemp3" => "5",
"SetTemp4" => "0",
_ => ""
};
}
private static string GetMappingDefaultValues(string columnName)
{
return columnName switch
{
"BitNumbers" => "",
_ => ""
};
}
private static string GetConfigrationDefaultValues(string columnName)
{
return columnName switch
{
"Max" => "0",
"Min" => "0",
"H_out" => "",
"FC_out" => "",
"SC_out" => "",
"kp" => "0",
"ki" => "0",
"kd" => "0",
"kl" => "0",
"Name" => "",
"I_Nuet" => "0",
"I_Mot1" => "0",
"I_Mot2" => "0",
"FC_Threshold" => "3",
"HeatConRange" => "50",
_ => ""
};
}
private static string GetErrorSettingsDefaultValues(string columnName)
{
return columnName switch
{
"gridFreq" => "50",
"phaseNumber" => "3",
"extPower" => "1",
"phaseVoltage" => "220",
_ => ""
};
}
private static string GetScreenDefaultValues(string columnName)
{
return columnName switch
{
"Brightness" => "100",
"DimSec" => "3300",
"OffSec" => "3600",
"Port" => "",
"BoundRate" => "19200",
"Parity" => "1",
"StopBits" => "0",
"SendingTime" => "50",
"WarningLimit" => "0.5",
"ErrorLimit" => "2",
_ => ""
};
}
// Legacy delete methods (kept for backward compatibility but now call migration)
public static void DeleteUsersCsv() => MigrateCsvFile("Users.csv", UsersCsvHeader, GetUsersDefaultValues);
public static void DeleteRecipeCsv() => MigrateCsvFile("Recipe.csv", RecipeCsvHeader, GetRecipeDefaultValues);
public static void DeleteMachineCsv() => MigrateCsvFile("Machine.csv", MachineCsvHeader, GetMachineDefaultValues);
public static void DeleteMappingCsv() => MigrateCsvFile("Mapping.csv", MappingCsvHeader, GetMappingDefaultValues);
public static void DeleteConfigrationCsv() => MigrateCsvFile("Configration.csv", ConfigrationCsvHeader, GetConfigrationDefaultValues);
public static void DeleteErrorSettingsCsv() => MigrateCsvFile("ErrorSettings.csv", ErrorSettingsCsvHeader, GetErrorSettingsDefaultValues);
public static void DeleteScreenCsv() => MigrateCsvFile("Screen.csv", ScreenCsvHeader, GetScreenDefaultValues);
}
}
============================================================
FILE: DaireApplication/DataBase/ErrorSettingsTable.cs
============================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication.DataBase
{
public class ErrorSettingsTable
{
public int Id { get; set; }
public int gridFreq { get; set; }
public int phaseNumber { get; set; }
public int phaseVoltage { get; set; }
public bool extPower { get; set; }
public List<ErrorSettingsTable>? ReadErrorSettings()
{
string filePath = DataPathManager.GetDataFilePath("ErrorSettings.csv");
if (!File.Exists(filePath))
return null;
string[] lines = File.ReadAllLines(filePath);
List<ErrorSettingsTable> errors = new();
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
errors.Add(new ErrorSettingsTable
{
Id = int.Parse(columns[0]),
gridFreq = int.Parse(columns[1]),
phaseNumber = int.Parse(columns[2]),
extPower = columns[3] == "1",
phaseVoltage = int.Parse(columns[4]),
});
}
return errors;
}
public bool UpdateError(ErrorSettingsTable updatedError)
{
string filePath = DataPathManager.GetDataFilePath("ErrorSettings.csv");
if (!File.Exists(filePath))
return false;
string[] lines = File.ReadAllLines(filePath);
bool updated = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (int.Parse(columns[0]) == updatedError.Id)
{
columns[1] = updatedError.gridFreq.ToString();
columns[2] = updatedError.phaseNumber.ToString();
columns[3] = updatedError.extPower ? "1" : "0";
columns[4] = updatedError.phaseVoltage .ToString();
lines[i] = string.Join(",", columns);
updated = true;
break;
}
}
if (updated)
{
File.WriteAllLines(filePath, lines);
return true;
}
return false;
}
}
}
============================================================
FILE: DaireApplication/DataBase/MachineTable.cs
============================================================
using AvaloniaApplication1.DataBase;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace DaireApplication.DataBase
{
public class MachineTable
{
public int Id { get; set; }
public float TankMaxHeat { get; set; } = 50;
public float PumbMaxHeat { get; set; } = 50;
public int PumbDelay { get; set; } = 60;
public int MixerDelay { get; set; } = 60;
public int HeatingDelay { get; set; } = 60;
public int CoolingDelay { get; set; } = 60;
public int PouringDelay { get; set; } = 60;
public float PumbMinHeat { get; set; } = -10;
public float AbsMaxHeat { get; set; } = 65;
public float AbsMinHeat { get; set; } = -14;
public float PreHeatingTemp { get; set; } = 5;
public float setTemp1 { get; set; } =0;
public float setTemp2 { get; set; } =-10;
public float setTemp3 { get; set; } =+5;
public float setTemp4 { get; set; } =+0;
public MachineTable ReadMachine()
{
string filePath = DataPathManager.GetDataFilePath("Machine.csv");
MachineTable machine = new MachineTable();
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
string[] columns = line.Split(',');
if (columns[0] == "1")
{
machine.Id = int.Parse(columns[0]);
machine.TankMaxHeat = float.Parse(columns[1]);
machine.PumbMaxHeat = float.Parse(columns[2]);
machine.PumbDelay = int.Parse(columns[3]);
machine.MixerDelay = int.Parse(columns[4]);
machine.HeatingDelay = int.Parse(columns[5]);
machine.CoolingDelay = int.Parse(columns[6]);
machine.PouringDelay = int.Parse(columns[7]);
machine.PumbMinHeat = int.Parse(columns[8]);
machine.AbsMaxHeat = int.Parse(columns[9]);
machine.AbsMinHeat = int.Parse(columns[10]);
machine.PreHeatingTemp = float.Parse(columns[11]);
machine.setTemp1 = float.Parse(columns[12]);
machine.setTemp2 = float.Parse(columns[13]);
machine.setTemp3 = float.Parse(columns[14]);
machine.setTemp4 = float.Parse(columns[15]);
return machine;
}
}
return null;
}
else
{
return null;
}
}
public bool UpdateMachine(MachineTable updatedMachine)
{
string filePath = DataPathManager.GetDataFilePath("Machine.csv");
if (!File.Exists(filePath))
return false;
string[] lines = File.ReadAllLines(filePath);
bool machineFound = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (columns.Length < 8)
continue;
if (int.Parse(columns[0]) == updatedMachine.Id)
{
columns[1] = updatedMachine.TankMaxHeat.ToString(CultureInfo.InvariantCulture);
columns[2] = updatedMachine.PumbMaxHeat.ToString(CultureInfo.InvariantCulture);
columns[3] = updatedMachine.PumbDelay.ToString();
columns[4] = updatedMachine.MixerDelay.ToString();
columns[5] = updatedMachine.HeatingDelay.ToString();
columns[6] = updatedMachine.CoolingDelay.ToString();
columns[7] = updatedMachine.PouringDelay.ToString();
columns[8] = updatedMachine.PumbMinHeat.ToString(CultureInfo.InvariantCulture);
columns[9] = updatedMachine.AbsMaxHeat.ToString(CultureInfo.InvariantCulture);
columns[10] = updatedMachine.AbsMinHeat.ToString(CultureInfo.InvariantCulture);
columns[11] = updatedMachine.PreHeatingTemp.ToString(CultureInfo.InvariantCulture);
columns[12] = updatedMachine.setTemp1.ToString(CultureInfo.InvariantCulture);
columns[13] = updatedMachine.setTemp2.ToString(CultureInfo.InvariantCulture);
columns[14] = updatedMachine.setTemp3.ToString(CultureInfo.InvariantCulture);
columns[15] = updatedMachine.setTemp4.ToString(CultureInfo.InvariantCulture);
lines[i] = string.Join(",", columns);
machineFound = true;
break;
}
}
if (machineFound)
{
File.WriteAllLines(filePath, lines);
return true;
}
return false;
}
}
}
============================================================
FILE: DaireApplication/DataBase/Mapping.cs
============================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DaireApplication.DataBase;
public class Mapping
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Address { get; set; } = "";
public bool IsRead { get; set; } = false;
public List<int> BitNumbers { get; set; } = new();
public ushort getSetTempAddress(int tempAddress)
{
string tAddress = "4000";
tempAddress -= 30004;
tAddress += tempAddress;
return ushort.Parse(tAddress);
}
public List<Mapping> ReadMappings()
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
List<Mapping> mappings = new();
if (File.Exists(filePath))
{
using StreamReader reader = new(filePath);
string header = reader.ReadLine();
while (!reader.EndOfStream)
{
string[] columns = reader.ReadLine().Split(',');
mappings.Add(new Mapping
{
Id = int.Parse(columns[0]),
Name = columns[1],
Address = columns[2],
IsRead = columns[3] == "1"|| columns[3] == "True",
BitNumbers =columns[4]!=""? columns[4].Split('|').Select(int.Parse).ToList():new List<int>()
});
}
return mappings;
}
return null;
}
public int GetMaxId()
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (File.Exists(filePath))
{
return File.ReadAllLines(filePath)
.Select(line => line.Split(','))
.Where(columns => columns.Length > 0)
.Select(columns => int.TryParse(columns[0], out int id) ? id : 0)
.Max();
}
return -1;
}
public Mapping ReadMappingById(string id)
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (File.Exists(filePath))
{
foreach (var line in File.ReadLines(filePath))
{
string[] columns = line.Split(',');
if (columns[0] == id)
{
return new Mapping
{
Id = int.Parse(columns[0]),
Name = columns[1],
Address = columns[2],
IsRead = columns[3] == "1",
BitNumbers = columns[4].Split('|').Select(int.Parse).ToList()
};
}
}
}
return null;
}
public bool AddMapping(Mapping data)
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (File.Exists(filePath))
{
string newEntry = string.Join(",", [
GetMaxId() + 1,
data.Name,
data.Address,
data.IsRead ? "1" : "0",
string.Join("|", data.BitNumbers)
]);
File.AppendAllText(filePath, newEntry + Environment.NewLine);
return true;
}
return false;
}
public bool DeleteMapping(string id)
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (File.Exists(filePath))
{
var filteredLines = File.ReadLines(filePath).Where(line => !line.StartsWith(id + ",")).ToArray();
File.WriteAllLines(filePath, filteredLines);
return true;
}
return false;
}
public bool UpdateMapping(Mapping updatedMapping)
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
bool mappingFound = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (columns.Length < 5)
continue;
if (int.Parse(columns[0]) == updatedMapping.Id)
{
columns[1] = updatedMapping.Name;
columns[2] = updatedMapping.Address;
columns[3] = updatedMapping.IsRead ? "1" : "0";
columns[4] = string.Join("|", updatedMapping.BitNumbers);
lines[i] = string.Join(",", columns);
mappingFound = true;
break;
}
}
if (mappingFound)
{
File.WriteAllLines(filePath, lines);
return true;
}
}
return false;
}
public bool DeleteBitNumber(int id, int bitNumber)
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (!File.Exists(filePath))
return false;
List<Mapping> records = ReadMappings();
Mapping? record = records.Find(x => x.Id == id);
if (record != null && record.BitNumbers.Remove(bitNumber)) // Remove bit number if found
{
string header;
using (StreamReader sr = new StreamReader(filePath))
{
header = sr.ReadLine() ?? string.Empty;
}
using (StreamWriter writer = new StreamWriter(filePath))
{
writer.WriteLine(header);
string bitNumbersStr = "";
foreach (var rec in records)
{
if (rec.Id==id)
{
bitNumbersStr = record.BitNumbers.Count > 0 ? string.Join("|", record.BitNumbers) : "";
writer.WriteLine($"{rec.Id},{rec.Name},{rec.Address},{rec.IsRead},{bitNumbersStr}");
}
else
{
bitNumbersStr = rec.BitNumbers.Count > 0 ? string.Join("|", rec.BitNumbers) : "";
writer.WriteLine($"{rec.Id},{rec.Name},{rec.Address},{rec.IsRead},{bitNumbersStr}");
}
}
}
return true;
}
return false;
}
}
============================================================
FILE: DaireApplication/DataBase/RecipeTable.cs
============================================================
using DaireApplication.DataBase;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace AvaloniaApplication1.DataBase
{
public class RecipeTable
{
public int Id { get; set; }
public string Name { get; set; }
public float TankTemp { get; set; } = 0;
public float FountainTemp { get; set; } = 0;
public bool? Mixer { get; set; } = false;
public bool? Fountain { get; set; }=false;
public bool? MoldHeater { get; set; }=false;
public bool? Vibration { get; set; } = false;
public bool? VibHeater { get; set; } = false;
public bool? Pedal { get; set; } = false;
public int PedalOnTime { get; set; } = 0;
public int PedalOffTime { get; set; } = 0;
public float HeatingGoal { get; set; } = 46;
public float CoolingGoal { get; set; } = 27;
public float PouringGoal { get; set; } = 30;
public RecipeTable()
{
// Mixer = null;
Fountain=null;
MoldHeater = null;
Vibration = null;
VibHeater = null;
Pedal = null;
}
public List<RecipeTable> ReadRecipes()
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
List<RecipeTable> recipes = new List<RecipeTable>();
if (File.Exists(filePath))
{
using (StreamReader reader = new StreamReader(filePath))
{
// Skip header
string header = reader.ReadLine();
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
string[] columns = line.Split(',');
recipes.Add(new RecipeTable
{
Id = int.Parse(columns[0]),
Name = columns[1],
TankTemp = float.Parse(columns[2]),
FountainTemp = float.Parse(columns[3]),
Mixer = columns[4] == "1",
Fountain = columns[5] == "1",
MoldHeater = columns[6]=="1",
Vibration = columns[7] == "1",
VibHeater = columns[8]== "1",
Pedal = columns[9]=="1",
PedalOnTime = int.Parse(columns[10]),
PedalOffTime = int.Parse(columns[11]),
HeatingGoal = float.Parse(columns[12]),
CoolingGoal = float.Parse(columns[13]),
PouringGoal = float.Parse(columns[14]),
});
}
}
return recipes;
}
else
{
return null;
}
}
public bool DoesNameExist(string searchName)
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
if (!File.Exists(filePath))
return false;
string[] lines = File.ReadAllLines(filePath);
return lines
.Select(line => line.Split(','))
.Where(columns => columns.Length > 1)
.Any(columns => string.Equals(columns[1].Trim(), searchName, StringComparison.OrdinalIgnoreCase));
}
public int GetMaxId()
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
int maxId = lines
.Select(line => line.Split(','))
.Where(columns => columns.Length > 0)
.Select(columns => int.TryParse(columns[0], out int id) ? id : 0)
.Max();
return maxId;
}
else
{
return -1;
}
}
public RecipeTable ReadRecipesById(string id)
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
RecipeTable recipe = new RecipeTable();
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
foreach (string line in lines)
{
string[] columns = line.Split(',');
if (columns[0] == id)
{
recipe.Id = int.Parse(columns[0]);
recipe.Name = columns[1];
recipe.TankTemp = float.Parse(columns[2]);
recipe.FountainTemp = float.Parse(columns[3]);
recipe.Mixer = columns[4] == "1";
recipe.Fountain = columns[5] == "1";
recipe.MoldHeater = columns[6] == "1";
recipe.Vibration = columns[7] == "1";
recipe.VibHeater = columns[8] == "1";
recipe.Pedal = columns[9] == "1";
recipe.PedalOnTime = int.Parse(columns[10]);
recipe.PedalOffTime = int.Parse(columns[11]);
recipe.HeatingGoal = float.Parse(columns[12]);
recipe.CoolingGoal = float.Parse(columns[13]);
recipe.PouringGoal = float.Parse(columns[14]);
return recipe;
}
}
return null;
}
else
{
return null;
}
}
public bool AddRecipe(RecipeTable data)
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
if (File.Exists(filePath))
{
string newEntry = string.Join(",", [GetMaxId() +1, data.Name,data.TankTemp, data.FountainTemp, data.Mixer.Value?"1":"0", data.Fountain.Value ? "1" : "0", data.MoldHeater.Value ? "1" : "0", data.Vibration.Value ? "1" : "0", data.VibHeater.Value ? "1" : "0", data.Pedal.Value ? "1":"0",data.PedalOnTime,data.PedalOffTime, data.HeatingGoal,data.CoolingGoal,data.PouringGoal]);
File.AppendAllText(filePath, newEntry + Environment.NewLine);
return true;
}
else
{
return false;
}
}
public bool DeleteRecipe(string id)
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
var filteredLines = lines.Where(line => !line.StartsWith(id + ",")).ToArray();
File.WriteAllLines(filePath, filteredLines);
return true;
}
else
{
return false;
}
}
public bool UpdateRecipe(RecipeTable updatedRecipe)
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
bool recipeFound = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (columns.Length < 15)
continue;
if (int.Parse(columns[0]) == updatedRecipe.Id)
{
columns[1] = updatedRecipe.Name;
columns[2] = updatedRecipe.TankTemp.ToString(System.Globalization.CultureInfo.InvariantCulture);
columns[3] = updatedRecipe.FountainTemp.ToString(System.Globalization.CultureInfo.InvariantCulture);
columns[4] = updatedRecipe.Mixer.Value ? "1" : "0";
columns[5] = updatedRecipe.Fountain.Value ? "1" : "0";
columns[6] = updatedRecipe.MoldHeater.Value ? "1" : "0";
columns[7] = updatedRecipe.Vibration.Value ? "1" : "0";
columns[8] = updatedRecipe.VibHeater.Value ? "1" : "0";
columns[9] = updatedRecipe.Pedal.Value ? "1" : "0";
columns[10] = updatedRecipe.PedalOnTime.ToString();
columns[11] = updatedRecipe.PedalOffTime.ToString();
columns[12] = updatedRecipe.HeatingGoal.ToString(System.Globalization.CultureInfo.InvariantCulture);
columns[13] = updatedRecipe.CoolingGoal.ToString(System.Globalization.CultureInfo.InvariantCulture);
columns[14] = updatedRecipe.PouringGoal.ToString(System.Globalization.CultureInfo.InvariantCulture);
lines[i] = string.Join(",", columns);
recipeFound = true;
break;
}
}
if (recipeFound)
{
File.WriteAllLines(filePath, lines);
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
}
}
============================================================
FILE: DaireApplication/DataBase/ScreeenTable.cs
============================================================
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DaireApplication.DataBase
{
public class ScreeenTable
{
public int Id { get; set; }
public int brightness { get; set; }
public float dimSec { get; set; }
public float offSec { get; set; }
public string port { get; set; }
public int boundRate { get; set; }
public int stopBits { get; set; }
public int parity { get; set; }
public int sendingTime { get; set; }
public double warningLimit { get; set; }
public double errorLimit { get; set; }
public List<ScreeenTable>? ReadScreens()
{
try
{
string filePath = DataPathManager.GetDataFilePath("Screen.csv");
if (!File.Exists(filePath))
return null;
string[] lines = File.ReadAllLines(filePath);
List<ScreeenTable> screens = new();
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (columns.Length < 8)
continue;
screens.Add(new ScreeenTable
{
Id = int.Parse(columns[0]),
brightness = int.Parse(columns[1]),
dimSec = float.Parse(columns[2]),
offSec = float.Parse(columns[3]),
port = columns[4],
boundRate = int.Parse(columns[5]),
stopBits = int.Parse(columns[6]),
parity = int.Parse(columns[7]),
sendingTime = int.Parse(columns[8]),
warningLimit = double.Parse(columns[9]),
errorLimit = double.Parse(columns[10]),
});
}
return screens;
}
catch (Exception)
{
return null;
}
}
public bool UpdateScreen(ScreeenTable updatedScreen)
{
string filePath = DataPathManager.GetDataFilePath("Screen.csv");
if (!File.Exists(filePath))
return false;
string[] lines = File.ReadAllLines(filePath);
bool updated = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (columns.Length < 8)
continue;
if (int.Parse(columns[0]) == updatedScreen.Id)
{
columns[1] = updatedScreen.brightness.ToString();
columns[2] = updatedScreen.dimSec.ToString();
columns[3] = updatedScreen.offSec.ToString();
columns[4] = updatedScreen.port;
columns[5] = updatedScreen.boundRate.ToString();
columns[6] = updatedScreen.stopBits.ToString();
columns[7] = updatedScreen.parity.ToString();
columns[8] = updatedScreen.sendingTime.ToString();
columns[9] = updatedScreen.warningLimit.ToString();
columns[10] = updatedScreen.errorLimit.ToString();
lines[i] = string.Join(",", columns);
updated = true;
break;
}
}
if (updated)
{
File.WriteAllLines(filePath, lines);
return true;
}
return false;
}
}
}
============================================================
FILE: DaireApplication/DataBase/UserTable.cs
============================================================
using DaireApplication.DataBase;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AvaloniaApplication1.DataBase
{
public class UserTable
{
public int Id { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public bool CanEdit { get; set; }
public bool IsAdmin { get; set; }
public bool IsActive { get; set; }
public List<UserTable> ReadUsers()
{
string filePath = DataPathManager.GetDataFilePath("Users.csv");
List<UserTable> users = new List<UserTable>();
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
for (int i = 1; i < lines.Length; i++) // Skip header
{
string[] columns = lines[i].Split(',');
users.Add(new UserTable
{
Id = int.Parse(columns[0]),
UserName = columns[1],
Password = columns[2],
CanEdit = columns[3] =="1" ?true:false,
IsAdmin=columns[4] =="1" ?true: false,
IsActive=columns[5] =="1" ?true: false,
});
}
return users;
}
else
{
return null;
}
}
public bool UpdateUser(UserTable updatedUser)
{
string filePath = DataPathManager.GetDataFilePath("Users.csv");
if (File.Exists(filePath))
{
string[] lines = File.ReadAllLines(filePath);
bool userFound = false;
for (int i = 1; i < lines.Length; i++)
{
string[] columns = lines[i].Split(',');
if (int.Parse(columns[0]) == updatedUser.Id)
{
columns[1] = updatedUser.UserName;
columns[2] = updatedUser.Password;
columns[3] = updatedUser.CanEdit ? "1" : "0";
columns[4] = updatedUser.IsAdmin ? "1" : "0";
columns[5] = updatedUser.IsActive ? "1" : "0";
lines[i] = string.Join(",", columns);
userFound = true;
break;
}
}
if (userFound)
{
File.WriteAllLines(filePath, lines);
return true;
}
}
return false;
}
}
}
============================================================
FILE: DaireApplication/Loops/CheckInterNetLoop.cs
============================================================
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication.Loops
{
public class CheckInterNetLoop
{
public static async void CheckInterNet(MainWindow _mainWindow)
{
string textToDelete = "";
while (true)
{
if (!Error.IsInternetAvailable())
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.ContentArea.Content is Home || _mainWindow.ContentArea.Content is Admin)
{
if (!_mainWindow.nowifiLogo.IsVisible)
{
_mainWindow.wifiLogo.IsVisible = false;
_mainWindow.nowifiLogo.IsVisible = true;
}
}
else
{
_mainWindow.wifiLogo.IsVisible = false;
_mainWindow.nowifiLogo.IsVisible = false;
}
//if (!_mainWindow.warningMsg.Text.Contains("No Internet Access"))
//{
// _mainWindow.warningMsg.Text += "\nNo Internet Access";
// _mainWindow.warningLogo.IsVisible = true;
//}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.ContentArea.Content is Home || _mainWindow.ContentArea.Content is Admin)
{
if (!_mainWindow.wifiLogo.IsVisible)
{
_mainWindow.nowifiLogo.IsVisible = false;
_mainWindow.wifiLogo.IsVisible = true;
}
}
else
{
_mainWindow.wifiLogo.IsVisible = false;
_mainWindow.nowifiLogo.IsVisible = false;
}
//if (_mainWindow.warningMsg.Text.Contains("No Internet Access"))
//{
// _mainWindow.warningMsg.Text=_mainWindow.warningMsg.Text.Replace("\nNo Internet Access", "");
//}
});
}
if (!string.IsNullOrEmpty(_mainWindow.warningMessage))
{
Dispatcher.UIThread.Post(() =>
{
if (!_mainWindow.warningMsg.Text.Contains($"\n-{_mainWindow.warningMessage}"))
{
textToDelete = _mainWindow.warningMessage;
_mainWindow.warningMsg.Text += $"\n-{_mainWindow.warningMessage}";
_mainWindow.warningLogo.IsVisible = true;
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.warningMsg.Text.Contains($"-{textToDelete}"))
{
_mainWindow.warningMsg.Text= _mainWindow.warningMsg.Text.Replace($"\n-{textToDelete}", "");
}
});
}
if ( string.IsNullOrEmpty(_mainWindow.warningMessage))
{
Dispatcher.UIThread.Post(() =>
{
_mainWindow.warningLogo.IsVisible = false;
});
}
Thread.Sleep(10);
}
}
}
}
============================================================
FILE: DaireApplication/Loops/InteractiveUILoop.cs
============================================================
using Avalonia.Media;
using Avalonia.Threading;
using AvaloniaApplication1.ViewModels;
using DaireApplication.DataBase;
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication.Loops
{
public class InteractiveUILoop
{
public static async void Flashing(MainWindow _mainWindow)
{
while (true)
{
// Flashing Pre Heater on
if (_mainWindow.isFlashPreHeating)
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.PreHeatingBtn.Foreground == Brushes.Transparent)
{
_mainWindow.PreHeatingBtn.Foreground = Brushes.White;
}
else
{
_mainWindow.PreHeatingBtn.Foreground = Brushes.Transparent;
}
});
}
// Flashing Pre Heater off
if (!_mainWindow.isFlashPreHeating)
{
Dispatcher.UIThread.Post(() =>
{
_mainWindow.PreHeatingBtn.Foreground = Brushes.White;
});
}
// Flashing Mixer on
if (_mainWindow.startMixerMotorFlashing == 1)
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.ContentArea.Content is Settings result)
{
var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label;
var motorRectangel = result.MixerSP.Children[2] as Avalonia.Controls.Shapes.Rectangle;
if (motorLable.Foreground.ToString() == "#ff231f20")
{
motorLable.Foreground = Brushes.Transparent ;
motorRectangel.Fill = Brushes.Transparent;
}
else
{
motorLable.Foreground = Brush.Parse("#ff231f20");
motorRectangel.Fill = Brush.Parse(_mainWindow.PassiveColor);
}
}
});
}
// Flashing Fountain on
if (_mainWindow.startFountainMotorFlashing == 1)
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.ContentArea.Content is Settings result)
{
var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label;
var fountainRectangel = result.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle;
if (fountainLable.Foreground.ToString() == "#ff231f20")
{
fountainLable.Foreground = Brushes.Transparent;
fountainRectangel.Fill = Brushes.Transparent;
}
else
{
fountainLable.Foreground = Brush.Parse("#ff231f20");
fountainRectangel.Fill = Brush.Parse(_mainWindow.PassiveColor);
}
}
});
}
Thread.Sleep(250);
}
}
}
}
============================================================
FILE: DaireApplication/Loops/ScreenLoop.cs
============================================================
using Avalonia.Threading;
using DaireApplication.Views;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace DaireApplication.Loops;
public class ScreenLoop
{
static void SetBrightness(int value)
{
//File.WriteAllText("/sys/class/backlight/backlight/brightness", value.ToString());
}
public static async void Screen(MainWindow _mainWindow)
{
var screenData = _mainWindow._screeen.ReadScreens()?[0];
SetBrightness((int)(screenData.brightness / 100 * 255));
while (true)
{
try
{
screenData = _mainWindow._screeen.ReadScreens()?[0];
if ((DateTime.Now - _mainWindow.lastActivity).TotalSeconds >= screenData?.offSec)
{
if (!MainWindow.isOff)
{
MainWindow.isOff = true;
SetBrightness(0);
}
}
else if ((DateTime.Now - _mainWindow.lastActivity).TotalSeconds >= screenData?.dimSec)
{
MainWindow.isOff = false;
SetBrightness(51); // 20% of 255
}
if (MainWindow.errors.Count > 0)
{
foreach (var item in MainWindow.errors.ToList())
{
if ((DateTime.Now - item.errorDate).TotalSeconds >= 2.5)
{
if (!item.isShowen)
{
Dispatcher.UIThread.Post(() =>
{
if (_mainWindow.errorMsg.Text.Contains($"- {item.GetDisplayNames(item.Condition)}"))
{
item.isShowen = true;
}
else
{
_mainWindow.errorMsg.Text += $"\n- {item.GetDisplayNames(item.Condition)}";
item.isShowen = true;
}
});
}
if (item.isDeleted)
{
Dispatcher.UIThread.Post(() =>
{
_mainWindow.errorMsg.Text = _mainWindow.errorMsg.Text
.Replace($"- {item.GetDisplayNames(item.Condition)}", "");
MainWindow.errors.Remove(item);
});
}
Dispatcher.UIThread.Post(() =>
{
_mainWindow.errorMsg.Text = _mainWindow.errorMsg.Text.Trim();
if (_mainWindow.ContentArea.Content is Settings settings && MainWindow.errors.Count > 0)
{
//_mainWindow.footerMsg.Text = "";
settings.mixerBtn.IsEnabled = false;
settings.fountainBtn.IsEnabled = false;
settings.moldHeaterBtn.IsEnabled = false;
settings.vibrationBtn.IsEnabled = false;
settings.vibHeaterBtn.IsEnabled = false;
_mainWindow.PreHeatingBtn.IsEnabled = false;
//_mainWindow.recipeStartBtn.IsEnabled = false;
}
});
}
}
if (MainWindow.errors.Count > 0)
{
if ((DateTime.Now - MainWindow.errors.Min(x => x.errorDate)).TotalSeconds >= 3.5)
{
Dispatcher.UIThread.Post(() =>
{
_mainWindow.errorLogo.IsVisible = true;
_mainWindow.errorTitel.Text = $"Error Number: {MainWindow.errors.Count}";
_mainWindow.errorMsg.Text = _mainWindow.errorMsg.Text.Trim();
//_mainWindow.footerMsg.Text = $"Error Numbers: {MainWindow.errors.Count}";
//_mainWindow.errorLogoBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
});
}
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
//MainWindow.errors.Clear();
_mainWindow.errorLogo.IsVisible = false;
_mainWindow.errorPopupOverlay.IsVisible = false;
if (_mainWindow.ContentArea.Content is Settings settings)
{
//_mainWindow.footerMsg.Text = "Ready";
settings.moldHeaterBtn.IsEnabled = true;
settings.vibrationBtn.IsEnabled = true;
settings.vibHeaterBtn.IsEnabled = true;
_mainWindow.recipeStartBtn.IsEnabled = true;
if (_mainWindow.startRecipe != 1)
{
_mainWindow.PreHeatingBtn.IsEnabled = true;
settings.mixerBtn.IsEnabled = true;
settings.fountainBtn.IsEnabled = true;
}
var isFountOn = false;
var isMixerOn = false;
var fountainMotor =_mainWindow._mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
var mixerMotor =_mainWindow._mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower());
if (isFountOn !=fountainMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0))
{
isFountOn = fountainMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0);
}
if (isMixerOn != mixerMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0))
{
isMixerOn = mixerMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0);
}
if (isFountOn && isMixerOn) // both motores are on
{
if (_mainWindow.startRecipe == 1 && (_mainWindow.Heating == 10 || _mainWindow.cooling == 10 || _mainWindow.pouring == 10))
{
_mainWindow.unPause = true;
}
}
}
});
}
await Task.Delay(10);
}
catch (Exception)
{
}
}
}
}
============================================================
FILE: DaireApplication/Loops/serialThreadLoop.cs
============================================================
using Avalonia.Threading;
using AvaloniaApplication1.ViewModels;
using DaireApplication.DataBase;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication.Loops
{
public class SerialRequest
{
public enum RequestType { Read, Write }
public RequestType Type { get; set; }
public byte[] Data { get; set; }
public int ExpectedLength { get; set; }
public TaskCompletionSource<byte[]> Completion { get; set; } = new();
}
public class serialThreadLoop
{
private static readonly ConcurrentQueue<SerialRequest> writeQueue = new();
private static readonly ConcurrentQueue<SerialRequest> readQueue = new();
private static bool keepSendingRunning = false;
public static Task<byte[]> EnqueueWrite(byte[] data, int expectedLength)
{
var req = new SerialRequest { Type = SerialRequest.RequestType.Write, Data = data, ExpectedLength = expectedLength };
writeQueue.Enqueue(req);
return req.Completion.Task;
}
public static Task<byte[]> EnqueueRead(byte[] data, int expectedLength)
{
var req = new SerialRequest { Type = SerialRequest.RequestType.Read, Data = data, ExpectedLength = expectedLength };
readQueue.Enqueue(req);
return req.Completion.Task;
}
public static async void SendViaSerial(MainWindow _mainWindow)
{
try
{
//Debug.WriteLine("SendViaSerial started");
// Start the keepSending background task if not already running
if (!keepSendingRunning)
{
//Debug.WriteLine("Starting KeepSendingLoop");
keepSendingRunning = true;
_ = Task.Run(() => KeepSendingLoop(_mainWindow));
}
List<float> values = new List<float>();
while (_mainWindow.serialThreadRunning)
{
//Debug.WriteLine($"SendViaSerial loop iteration - Port status: {(_mainWindow._port?.IsOpen ?? false)}");
if (_mainWindow._port != null && _mainWindow._port.IsOpen)
{
if (_mainWindow.reSendHolding)
{
values.Clear();
_mainWindow._configrations = _mainWindow._config.ReadConfigrations();
values.Add(_mainWindow.holdingRegister.resetError);
values.Add(_mainWindow.holdingRegister.hvOut);
values.Add(_mainWindow.holdingRegister.lvOut);
values.Add(_mainWindow.holdingRegister.motor);
values.Add(_mainWindow.holdingRegister.setTemp1);
values.Add(_mainWindow.holdingRegister.setTemp2);
values.Add(_mainWindow.holdingRegister.setTemp3);
values.Add(_mainWindow.holdingRegister.setTemp4);
values.Add((int)(_mainWindow._configrations[0].i_neut * 10));
values.Add((int)(_mainWindow._configrations[0].i_mot1 * 10));
values.Add((int)(_mainWindow._configrations[0].i_mot2 * 10));
foreach (var item in _mainWindow._configrations)
{
values.Add(item.Max * 10);
values.Add(item.Min * 10);
values.Add(ConvertToDecimal(item.H_out.ToList()));
values.Add(ConvertToDecimal(item.FC_out.ToList()));
values.Add(ConvertToDecimal(item.SC_out.ToList()));
values.Add(item.FC_Threshold * 10);
values.Add(item.HeatConRange * 10);
values.Add(item.kp);
values.Add(item.ki);
values.Add(item.kd);
values.Add(item.kl);
}
_mainWindow._port.DiscardInBuffer();
_mainWindow._port.DiscardOutBuffer();
byte[] requstConfig = await _mainWindow._modBusMaster.WriteMultipleRegisters(0, values.ToArray());
await EnqueueWrite(requstConfig, 7);
_mainWindow.reSendHolding = false;
}
if (_mainWindow.sendConfig)
{
values.Clear();
_mainWindow._configrations = _mainWindow._config.ReadConfigrations();
if (!_mainWindow.dontResetOutPuts)
{
values.Add(0);
values.Add(0);
values.Add(0);
values.Add(-10000);
values.Add(-10000);
values.Add(-10000);
values.Add(-10000);
}
values.Add((int)(_mainWindow._configrations[0].i_neut * 10));
values.Add((int)(_mainWindow._configrations[0].i_mot1 * 10));
values.Add((int)(_mainWindow._configrations[0].i_mot2 * 10));
foreach (var item in _mainWindow._configrations)
{
values.Add(item.Max * 10);
values.Add(item.Min * 10);
values.Add(ConvertToDecimal(item.H_out.ToList()));
values.Add(ConvertToDecimal(item.FC_out.ToList()));
values.Add(ConvertToDecimal(item.SC_out.ToList()));
values.Add(item.FC_Threshold * 10);
values.Add(item.HeatConRange * 10);
values.Add(item.kp);
values.Add(item.ki);
values.Add(item.kd);
values.Add(item.kl);
}
byte[] requstConfig = await _mainWindow._modBusMaster.WriteMultipleRegisters(_mainWindow.dontResetOutPuts ? (ushort)8 : (ushort)1, values.ToArray());
await EnqueueWrite(requstConfig, 7);
_mainWindow.sendConfig = false;
_mainWindow.dontResetOutPuts = false;
}
if (_mainWindow.restBoard)
{
_mainWindow.holdingRegister.hvOut = 0;
_mainWindow.holdingRegister.lvOut = 0;
_mainWindow.holdingRegister.motor = 0;
_mainWindow.holdingRegister.setTemp1 = -10000;
_mainWindow.holdingRegister.setTemp2 = -10000;
_mainWindow.holdingRegister.setTemp3 = -10000;
_mainWindow.holdingRegister.setTemp4 = -10000;
// Send reset data directly without using the async pattern
List<float> resetValues = new List<float>();
resetValues.Add(_mainWindow.holdingRegister.resetError);
resetValues.Add(_mainWindow.holdingRegister.hvOut);
resetValues.Add(_mainWindow.holdingRegister.lvOut);
resetValues.Add(_mainWindow.holdingRegister.motor);
resetValues.Add(_mainWindow.holdingRegister.setTemp1);
resetValues.Add(_mainWindow.holdingRegister.setTemp2);
resetValues.Add(_mainWindow.holdingRegister.setTemp3);
resetValues.Add(_mainWindow.holdingRegister.setTemp4);
byte[] resetRequest = await _mainWindow._modBusMaster.WriteMultipleRegisters(0, resetValues.ToArray());
await EnqueueWrite(resetRequest, 7);
_mainWindow.restBoard = false;
}
// Check if there's a pending write request
if (_mainWindow._writeCompletionSource?.Task.Status == TaskStatus.WaitingForActivation)
{
List<float> writingValues = new List<float>();
writingValues.Add(_mainWindow.holdingRegister.resetError);
writingValues.Add(_mainWindow.holdingRegister.hvOut);
writingValues.Add(_mainWindow.holdingRegister.lvOut);
writingValues.Add(_mainWindow.holdingRegister.motor);
writingValues.Add(_mainWindow.holdingRegister.setTemp1);
writingValues.Add(_mainWindow.holdingRegister.setTemp2);
writingValues.Add(_mainWindow.holdingRegister.setTemp3);
writingValues.Add(_mainWindow.holdingRegister.setTemp4);
byte[] requstConfig = await _mainWindow._modBusMaster.WriteMultipleRegisters(0, writingValues.ToArray());
var result = await EnqueueWrite(requstConfig, 7);
// Signal completion
bool success = result.Length != 1 || result[0] != 0xFF;
_mainWindow.SetWriteComplete(success);
}
var requstReadingInputs = await _mainWindow._modBusMaster.ReadInputRegisters(0, 18);
await EnqueueRead(requstReadingInputs, 41);
}
}
}
catch (Exception ex)
{
}
}
private static async Task KeepSendingLoop(MainWindow _mainWindow)
{
//Debug.WriteLine("KeepSendingLoop started");
var startTime = DateTime.Now;
int intervalMs = _mainWindow.screenData.sendingTime;
int requestCount = 0;
while (_mainWindow.serialThreadRunning)
{
try
{
_mainWindow.screenData = _mainWindow._screeen.ReadScreens()[0];
//Debug.WriteLine($"KeepSendingLoop iteration - Port status: {(_mainWindow._port?.IsOpen ?? false)}, SendingTime: {_mainWindow.screenData.sendingTime}ms");
// Skip if port is not valid
if (_mainWindow._port == null || !_mainWindow._port.IsOpen)
{
//Debug.WriteLine("Port not valid, waiting...");
await Task.Delay(100); // Wait a bit before checking again
continue;
}
var scheduledTime = startTime.AddMilliseconds(requestCount * intervalMs);
var now = DateTime.Now;
var waitTime = (scheduledTime - now).TotalMilliseconds;
if (waitTime > 0)
await Task.Delay((int)waitTime);
SerialRequest req = null;
if (!writeQueue.TryPeek(out req))
readQueue.TryPeek(out req);
if (req != null)
{
var requestStart = DateTime.Now;
var response = await keepSendingScenario(_mainWindow, req.Data, req.ExpectedLength,_mainWindow.screenData.sendingTime);
var requestEnd = DateTime.Now;
var requestElapsed = (requestEnd - requestStart).TotalMilliseconds;
if (response.Length != 1 || response[0] != 0xFF)
{
//Debug.WriteLine($"SUCCESS: Total time for request: {requestElapsed} ms");
if (req.Type == SerialRequest.RequestType.Read)
{
_mainWindow.inputesResponse = response;
}
req.Completion.SetResult(response);
}
else // failed after retries or timeout
{
//Debug.WriteLine($"FAILED: Total time for request: {requestElapsed} ms");
req.Completion.SetResult(response); // set failure result
}
if (req.Type == SerialRequest.RequestType.Write)
writeQueue.TryDequeue(out _);
else
readQueue.TryDequeue(out _);
}
requestCount++;
// If we are behind schedule, catch up
if ((DateTime.Now - startTime).TotalMilliseconds > requestCount * intervalMs)
requestCount = (int)((DateTime.Now - startTime).TotalMilliseconds / intervalMs);
}
catch (Exception ex)
{
//Debug.WriteLine($"Error in KeepSendingLoop: {ex.Message}");
await Task.Delay(100); // Wait a bit before retrying
}
}
}
private static async Task<byte[]> keepSendingScenario(MainWindow _mainWindow, byte[] request, int expectedLength, int interval)
{
// Enforce minimum interval between packets
using var cts = new CancellationTokenSource();
int SENDING_INTERVAL = interval; // Minimum interval between sends
var now = DateTime.Now;
var elapsed = (now - _mainWindow._lastPacketSendTime).TotalMilliseconds;
if (elapsed < _mainWindow.screenData.sendingTime)
{
await Task.Delay((int)(SENDING_INTERVAL - elapsed));
}
_mainWindow._lastPacketSendTime = DateTime.Now;
//Debug.WriteLine("keepSending started");
// Calculate 4 character delay based on baud rate
double fourCharDelay = (1.0 / _mainWindow.screenData.boundRate) * 44000;
int noResponseRetryCount = 0;
const int MAX_NO_RESPONSE_RETRIES = 3; // Try 3 times, once per second
const int NO_RESPONSE_TIMEOUT = 1000; // 1 second between no-response retries
const int TOTAL_INVALID_RETRY_TIME = 3000; // 3 seconds total for invalid responses
var startTime = DateTime.Now;
var lastSendTime = DateTime.Now;
var lastValidResponseTime = DateTime.Now;
bool hadValidResponse = false;
while ((DateTime.Now - startTime).TotalMilliseconds < TOTAL_INVALID_RETRY_TIME)
{
// Calculate time since last send
var timeSinceLastSend = (DateTime.Now - lastSendTime).TotalMilliseconds;
var timeSinceLastValidResponse = (DateTime.Now - lastValidResponseTime).TotalMilliseconds;
// Check for communication timeout
if (timeSinceLastValidResponse >= TOTAL_INVALID_RETRY_TIME && !hadValidResponse)
{
//Debug.WriteLine("No valid response received within 3 seconds");
if (!MainWindow.errors.Any(x => x.Condition == Error.GridCondition.NoBoardCom))
{
MainWindow.errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.NoBoardCom
});
}
}
// For no response case, check frequently for response
if (noResponseRetryCount > 0 && timeSinceLastSend < NO_RESPONSE_TIMEOUT)
{
// Check for response every 10ms
if (_mainWindow._port != null && _mainWindow._port.IsOpen)
{
if (_mainWindow._port.BytesToRead >= expectedLength)
{
// Wait 4-char delay when we have enough bytes
await Task.Delay((int)fourCharDelay);
var response = await TryReadOnce(_mainWindow, expectedLength, cts.Token);
//Debug.WriteLine($"Response received during wait after {timeSinceLastSend}ms");
if (response.Length == expectedLength && IsValidCrc(response))
{
hadValidResponse = true;
lastValidResponseTime = DateTime.Now; // Reset valid response timer
var err = MainWindow.errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoBoardCom);
if (err != null) err.isDeleted = true;
// For valid response, still respect minimum interval
//if (timeSinceLastSend < SENDING_INTERVAL)
//{
// var remainingTime = SENDING_INTERVAL - timeSinceLastSend;
// Debug.WriteLine($"Valid response received before {SENDING_INTERVAL}ms, waiting {remainingTime}ms");
// await Task.Delay((int)remainingTime);
//}
return response;
}
// For any response (even invalid), increment retry count and continue immediately
noResponseRetryCount++;
if (noResponseRetryCount >= MAX_NO_RESPONSE_RETRIES)
{
//Debug.WriteLine("Max retries exceeded");
if (!MainWindow.errors.Any(x => x.Condition == Error.GridCondition.NoBoardCom))
{
MainWindow.errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.NoBoardCom
});
}
return new byte[] { 0xFF };
}
// Break wait and send next retry immediately
lastSendTime = DateTime.Now.AddMilliseconds(-NO_RESPONSE_TIMEOUT); // Force immediate retry
break;
}
/*await Task.Delay(10);*/ // Small delay between checks
continue;
}
}
// For invalid response case, wait minimum interval between retries
if (timeSinceLastSend < SENDING_INTERVAL)
{
await Task.Delay(1); // Minimal delay to prevent tight loop
continue;
}
// Send the request
_mainWindow._port.Write(request, 0, request.Length);
lastSendTime = DateTime.Now;
//Debug.WriteLine($"Sent request at {lastSendTime:HH:mm:ss.fffffff}");
// Wait 4-char delay after sending
await Task.Delay((int)fourCharDelay);
// Try to read response
if (_mainWindow._port != null && _mainWindow._port.IsOpen && _mainWindow._port.BytesToRead >= expectedLength)
{
// Wait another 4-char delay when we have enough bytes
await Task.Delay((int)fourCharDelay);
var response = await TryReadOnce(_mainWindow, expectedLength, cts.Token);
// Handle valid response
if (response.Length >= expectedLength && IsValidCrc(response))
{
hadValidResponse = true;
lastValidResponseTime = DateTime.Now; // Reset valid response timer
var err = MainWindow.errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoBoardCom);
if (err != null) err.isDeleted = true;
return response;
}
}
// Handle invalid/no response
noResponseRetryCount++;
//Debug.WriteLine($"Invalid/No response, attempt {noResponseRetryCount} of {MAX_NO_RESPONSE_RETRIES}");
if (noResponseRetryCount >= MAX_NO_RESPONSE_RETRIES)
{
//Debug.WriteLine("Max retries exceeded");
if (!MainWindow.errors.Any(x => x.Condition == Error.GridCondition.NoBoardCom))
{
MainWindow.errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.NoBoardCom
});
}
return new byte[] { 0xFF };
}
}
return new byte[] { 0xFF };
}
private static async Task<byte[]> TryReadOnce(MainWindow _mainWindow, int expectedLength, CancellationToken token)
{
var buffer = new List<byte>();
var startTime = DateTime.UtcNow;
var timeout = 3000;
while ((DateTime.UtcNow - startTime).TotalMilliseconds < timeout)
{
token.ThrowIfCancellationRequested();
if (_mainWindow._port != null && _mainWindow._port.IsOpen)
{
int available = _mainWindow._port.BytesToRead;
if (available > 0)
{
byte[] temp = new byte[available];
_mainWindow._port.Read(temp, 0, available);
buffer.AddRange(temp);
if (buffer.Count >= 3)
{
var response = buffer.ToArray();
if (response.Length < expectedLength)
{
//Debug.WriteLine($"Invalid response length: got {response.Length}, expected {expectedLength}");
return new byte[] { 0xFF };
}
if (!IsValidCrc(response))
{
//Debug.WriteLine("Invalid CRC in response");
return new byte[] { 0xFF };
}
var err = MainWindow.errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoBoardCom);
if (err != null) err.isDeleted = true;
return response;
}
}
}
await Task.Delay(1);
}
//Debug.WriteLine("Response timeout");
return new byte[] { 0xFF };
}
private static bool IsValidCrc(byte[] data)
{
if (data.Length < 3) return false;
ushort calculated = ComputeCRC(data.AsSpan(0, data.Length - 2));
ushort received = (ushort)(data[^2] | (data[^1] << 8));
return calculated == received;
}
private static ushort ComputeCRC(ReadOnlySpan<byte> data)
{
ushort crc = 0xFFFF;
foreach (var b in data)
{
crc ^= b;
for (int i = 0; i < 8; i++)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
return crc;
}
static int ConvertToDecimal(List<int> bitPositions)
{
int result = 0;
if (bitPositions.Count() == 1 && bitPositions[0] == -1)
{
return result;
}
foreach (var pos in bitPositions)
{
if (pos is >= 0 and < 16)
result |= 1 << pos;
}
return result;
}
}
}
============================================================
FILE: DaireApplication/Loops/TouchLoop.cs
============================================================
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication.Loops
{
public class TouchLoop
{
static void SetBrightness(int value)
{
//File.WriteAllText("/sys/class/backlight/backlight/brightness", value.ToString());
}
public static async void Touch(MainWindow _mainWindow)
{
static void WatchInput(int bright, MainWindow _mainWindow)
{
string inputDevice = "/dev/input/event1"; // adjust based on your touch device
using (FileStream fs = new FileStream(inputDevice, FileMode.Open, FileAccess.Read))
{
byte[] buffer = new byte[24];
fs.Read(buffer, 0, buffer.Length);
_mainWindow.lastActivity = DateTime.Now;
SetBrightness(bright); // Restore brightness if touch
}
}
var screenData = _mainWindow._screeen.ReadScreens()?[0];
while (true)
{
try
{
screenData = _mainWindow._screeen.ReadScreens()?[0];
int brightnessValue = (int)((screenData.brightness) / 100.0 * 255);
MainWindow.isOff = false;
//WatchInput(brightnessValue, _mainWindow);
Thread.Sleep(200);
}
catch (Exception)
{
}
}
}
}
}
============================================================
FILE: DaireApplication/Properties/PublishProfiles/FolderProfile.pubxml
============================================================
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>C:\Users\Swb\Desktop\test</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
<PublishReadyToRun>false</PublishReadyToRun>
<PublishTrimmed>false</PublishTrimmed>
</PropertyGroup>
</Project>
============================================================
FILE: DaireApplication/ViewModels/Error.cs
============================================================
using Avalonia.Controls;
using Avalonia.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using static DaireApplication.Views.MainWindow;
namespace DaireApplication.ViewModels
{
public class Error
{
public enum GridCondition
{
GridFrequencyHigh,
GridFrequencyLow,
GridVACHigh,
GridVACLow,
NoExternalPower,
MissingPhase,
PhaseSequence,
LoadDisconnection,
MotorDisconnection,
NoBoardCom,
NoInternetAccess,
ComPort1,
ComPort2,
HiCurrNeut,
HiCurrMot1,
HiCurrMot2,
}
public DateTime errorDate { get; set; }
public GridCondition Condition { get; set; }
public bool isShowen { get; set; } = false;
public bool isDeleted { get; set; } = false;
public string GetDisplayNames(GridCondition condition)
{
return condition switch
{
GridCondition.GridFrequencyHigh => "Grid Frequency High",
GridCondition.GridFrequencyLow => "Grid Frequency Low",
GridCondition.GridVACHigh => "Grid VAC High",
GridCondition.GridVACLow => "Grid VAC Low",
GridCondition.NoExternalPower => "No External Power",
GridCondition.MissingPhase => "Missing Phase",
GridCondition.PhaseSequence => "Phase Sequence",
GridCondition.LoadDisconnection => "Load Disconnection",
GridCondition.MotorDisconnection => "Motor Disconnection",
GridCondition.NoBoardCom => "Communication Timeout",
GridCondition.NoInternetAccess => "No InternetAccess",
GridCondition.ComPort1 => "Com Port1",
GridCondition.ComPort2 => "Com Port2",
GridCondition.HiCurrNeut=> "Hi Curr Neut",
GridCondition.HiCurrMot1=> "Hi Curr Mot1",
GridCondition.HiCurrMot2=> "Hi Curr Mot2",
_ => string.Empty
};
}
public static bool IsInternetAvailable()
{
try
{
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (var networkInterface in networkInterfaces)
{
if (networkInterface.OperationalStatus == OperationalStatus.Up)
{
using (var ping = new Ping())
{
var reply = ping.Send("8.8.8.8", 3000); // Pinging Google DNS server with a timeout of 3000ms
if (reply != null && reply.Status == IPStatus.Success)
{
return true; // Internet is available
}
}
}
}
}
catch (Exception)
{
return false; // Return false if there is any exception (e.g., no network interface found, or errors during checking)
}
return false; // Return false if no network interfaces are available or no successful ping
}
}
}
============================================================
FILE: DaireApplication/ViewModels/HoldingRegister.cs
============================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DaireApplication.ViewModels
{
public class HoldingRegister
{
public ushort resetError { get; set; } = 0;
public ushort hvOut { get; set; } = 0;
public ushort lvOut { get; set; } = 0;
public ushort motor { get; set; } = 0;
public int setTemp1 { get; set; } = -10000;
public int setTemp2 { get; set; } = -10000;
public int setTemp3 { get; set; } = -10000;
public int setTemp4 { get; set; } = -10000;
}
}
============================================================
FILE: DaireApplication/ViewModels/MainWindowViewModel.cs
============================================================
namespace DaireApplication.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
public string Greeting { get; } = "Welcome to Avalonia!";
}
}
============================================================
FILE: DaireApplication/ViewModels/ModBusMaster.cs
============================================================
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace AvaloniaApplication1.ViewModels
{
public class ModBusMaster
{
public byte slaveId { get; set; } = 0x01; // Slave ID (your ESP slave ID)
//byte functionCode = 0x05; // Function code for Write Single Coil
//byte coilAddressHigh = 0x00; // Coil address (MSB)
//byte coilAddressLow = 0x00; // Coil address (LSB)
//byte coilValueHigh = 0x00; // Coil value (0xFF00 to turn on, 0x0000 to turn off)
//byte coilValueLow = 0x00;
// Function to read coils
public async Task<bool[]> ReadCoils(SerialPort port, ushort startAddress, ushort numberOfCoils)
{
try
{
byte functionCode = 0x01; // Function code for Read Coils
byte[] frame = new byte[6]; // Request frame size (without CRC)
// Construct the request frame
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code (0x01 for Read Coils)
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(numberOfCoils >> 8); // Number of coils high byte
frame[5] = (byte)(numberOfCoils & 0xFF); // Number of coils low byte
// Calculate CRC and append it to the frame
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
// Send the frame over the serial port
port.DiscardOutBuffer();
port.DiscardInBuffer();
port.Write(fullFrame, 0, fullFrame.Length);
Thread.Sleep(500);
Console.WriteLine("Read Coils request sent.");
// Buffer for the response (modbus slave response size can vary)
byte[] response = new byte[256];
int bytesRead = port.Read(response, 0, response.Length);
Console.WriteLine("Response Coils sent.");
// Ensure that the response is valid (check slave address and function code)
if (response[0] != slaveId || response[1] != functionCode)
{
Console.WriteLine("Invalid response or error in slave response.");
return null;
}
// Calculate the number of bytes based on the number of coils
int expectedByteCount = (numberOfCoils + 7) / 8;
if (response[2] != expectedByteCount)
{
Console.WriteLine("Incorrect byte count in the response.");
return null;
}
// The response bytes are in bit form, and we need to extract them
bool[] coilStates = new bool[numberOfCoils]; // Array to store the coil states
int byteIndex = 3; // Start reading from byte 3 (after slave ID and function code)
byte coilByte = response[byteIndex]; // The byte representing the coil states
// Loop over all coils and check the corresponding bit
for (int coilIndex = 0; coilIndex < numberOfCoils; coilIndex++)
{
// Check the state of the coil by checking the corresponding bit in coilByte
coilStates[coilIndex] = coilByte == 1 ? true : false; /*(coilByte & (1 << (7 - coilIndex))) != 0;*/
}
if (coilStates==null)
{
Console.WriteLine("status wael: null");
}
else
{
Console.WriteLine($"status: {coilStates[0]}");
}
return coilStates;
}
catch (Exception ex)
{
Console.WriteLine($"error wael: {ex.Message}");
return null;
}
}
// Function to write a single coil
public async Task<byte[]> WriteSingleCoil(ushort coilAddress, bool state)
{
byte functionCode = 0x05;
byte[] frame = new byte[6];
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(coilAddress >> 8); // Coil address high byte
frame[3] = (byte)(coilAddress & 0xFF); // Coil address low byte
frame[4] = (byte)(state ? 0xFF : 0x00); // Coil value (ON=0xFF, OFF=0x00)
frame[5] = (byte)(0x00); // Coil value (ON=0xFF, OFF=0x00)
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
// Function to write multiple coils
public byte[] WriteMultipleCoils( ushort startAddress, bool[] coilValues)
{
byte functionCode = 0x0F;
int byteCount = (coilValues.Length + 7) / 8; // Calculate the number of bytes needed
byte[] frame = new byte[5 + byteCount]; // Basic frame without CRC
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(coilValues.Length); // Number of coils
frame[5] = (byte)byteCount; // Number of bytes to follow (coil values)
for (int i = 0; i < coilValues.Length; i++)
{
int byteIndex = 5 + 1 + (i / 8); // Start at byte 6, accounting for byte count
if (coilValues[i])
{
frame[byteIndex] |= (byte)(1 << (i % 8)); // Set the bit corresponding to the coil
}
}
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
// Function to write multiple registers
public async Task<byte[]> WriteSingleRegister(ushort startAddress, int value)
{
byte functionCode = 0x06; // Function code for writing a single register
byte[] frame = new byte[6]; // Basic frame without CRC
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(value >> 8); // Register value high byte
frame[5] = (byte)(value & 0xFF); // Register value low byte
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
public async Task<byte[]> WriteSingleRegister(ushort startAddress, ushort value)
{
byte functionCode = 0x06; // Function code for writing a single register
byte[] frame = new byte[6]; // Basic frame without CRC
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(value >> 8); // Register value high byte
frame[5] = (byte)(value & 0xFF); // Register value low byte
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
public async Task<byte[]> ReadHoldingRegister(ushort startAddress, ushort numberOfRegisters)
{
byte functionCode = 0x03; // Function code for reading holding registers
byte[] frame = new byte[6]; // Basic frame without CRC
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(numberOfRegisters >> 8); // Number of registers high byte
frame[5] = (byte)(numberOfRegisters & 0xFF); // Number of registers low byte
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
public async Task<byte[]> ReadInputRegisters(ushort startAddress, ushort numberOfRegisters)
{
byte functionCode = 0x04; // Function code for reading input registers
byte[] frame = new byte[6]; // Basic frame without CRC
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(numberOfRegisters >> 8); // Number of registers high byte
frame[5] = (byte)(numberOfRegisters & 0xFF); // Number of registers low byte
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
public async Task<byte[]> WriteMultipleRegisters(ushort startAddress, float[] values)
{
byte functionCode = 0x10; // Function code for writing multiple registers
byte byteCount = (byte)(values.Length * 2); // Total number of bytes for values
byte[] frame = new byte[7 + byteCount]; // Frame without CRC
frame[0] = slaveId; // Slave address
frame[1] = functionCode; // Function code
frame[2] = (byte)(startAddress >> 8); // Start address high byte
frame[3] = (byte)(startAddress & 0xFF); // Start address low byte
frame[4] = (byte)(values.Length >> 8); // Number of registers high byte
frame[5] = (byte)(values.Length & 0xFF); // Number of registers low byte
frame[6] = byteCount; // Byte count
for (int i = 0; i < values.Length; i++)
{
short val = unchecked((short)values[i]);
frame[7 + i * 2] = (byte)(val >> 8); // Register value high byte
frame[8 + i * 2] = (byte)(val & 0xFF); // Register value low byte1
}
// Calculate CRC and append it
byte[] crc = CalculateCRC(frame);
byte[] fullFrame = new byte[frame.Length + crc.Length];
Array.Copy(frame, fullFrame, frame.Length);
Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length);
return fullFrame;
}
// Function to calculate CRC16 for Modbus RTU frame
public byte[] CalculateCRC(byte[] data)
{
ushort crc = 0xFFFF;
foreach (byte byteData in data)
{
crc ^= byteData;
for (int i = 8; i > 0; i--)
{
if ((crc & 0x0001) == 0x0001)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
return new byte[] { (byte)(crc & 0xFF), (byte)((crc >> 8) & 0xFF) };
}
}
}
============================================================
FILE: DaireApplication/ViewModels/ViewModelBase.cs
============================================================
using ReactiveUI;
namespace DaireApplication.ViewModels
{
public class ViewModelBase : ReactiveObject
{
}
}
============================================================
FILE: DaireApplication/ViewModels/X11CursorHider.cs
============================================================
using System;
using System.Runtime.InteropServices;
public class X11CursorHider
{
const string X11Lib = "libX11.so";
[DllImport(X11Lib)]
static extern IntPtr XOpenDisplay(IntPtr display);
[DllImport(X11Lib)]
static extern int XCloseDisplay(IntPtr display);
[DllImport(X11Lib)]
static extern IntPtr XCreatePixmap(IntPtr display, IntPtr drawable, uint width, uint height, uint depth);
[DllImport(X11Lib)]
static extern IntPtr XCreateBitmapFromData(IntPtr display, IntPtr drawable, byte[] data, uint width, uint height);
[DllImport(X11Lib)]
static extern IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground, ref XColor background, uint x, uint y);
[DllImport(X11Lib)]
static extern int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
[DllImport(X11Lib)]
static extern int XFreeCursor(IntPtr display, IntPtr cursor);
[DllImport(X11Lib)]
static extern int XFlush(IntPtr display);
[DllImport(X11Lib)]
static extern IntPtr XDefaultRootWindow(IntPtr display);
[StructLayout(LayoutKind.Sequential)]
struct XColor
{
public ulong pixel;
public ushort red, green, blue;
public byte flags;
public byte pad;
}
public static void HideCursor()
{
IntPtr display = XOpenDisplay(IntPtr.Zero);
if (display == IntPtr.Zero)
{
Console.WriteLine("Cannot open X display");
return;
}
IntPtr root = XDefaultRootWindow(display);
byte[] emptyData = new byte[1] { 0 }; // 1x1 empty bitmap
IntPtr pixmap = XCreateBitmapFromData(display, root, emptyData, 1, 1);
XColor dummy = new XColor();
IntPtr invisibleCursor = XCreatePixmapCursor(display, pixmap, pixmap, ref dummy, ref dummy, 0, 0);
XDefineCursor(display, root, invisibleCursor);
XFlush(display);
// Keep the cursor hidden until app closes, remember to call:
// XFreeCursor(display, invisibleCursor);
// XCloseDisplay(display);
}
}
============================================================
FILE: DaireApplication/Views/UserController/Admin.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="DaireApplication.Admin" FontFamily="sans serif"
Background="#b3b3b3"
Width="1280" Height="620" >
<Grid RowDefinitions="*">
<Grid.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="#A4275D"></Setter>
<Setter Property="Background" Value="#E6E6E6"></Setter>
<Setter Property="RenderTransform" Value="scale(1.11)"></Setter>
</Style>
<Style Selector="Button">
<Setter Property="Padding" Value="0,-5,0,0"></Setter>
<Setter Property="VerticalContentAlignment" Value="Center" ></Setter>
<Setter Property="HorizontalContentAlignment" Value="Center" ></Setter>
</Style>
</Grid.Styles>
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,*">
<!--1st col (section one)-->
<Grid Grid.Column="0" ColumnDefinitions="*,*,*">
<Grid Grid.Column="0" RowDefinitions="1.2*,*" Margin="2,20,0,0" ZIndex="99" >
<StackPanel Grid.Row="0" Orientation="Vertical" Margin="0,10,0,0" Spacing="10">
<!-- A "card" with a label on top, and a row for minus-button / numeric text / plus-button -->
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="180"
>
<StackPanel Spacing="20">
<Grid >
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="HELIX JACKET MAX HEATING TEMP."
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*"
Grid.Row="2"
>
<Grid ColumnDefinitions="Auto,*,Auto" Tag="pMaxt">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesHelixTempBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center" ZIndex="-1">
<!-- Numeric text -->
<TextBlock x:Name="fountainMaxTemp" Grid.Column="1"
Text="60.0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="0,0,0,0" ZIndex="-1"/>
<TextBlock Grid.Column="1"
Text="°C"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="0,0,0,0" ZIndex="-1"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusHelixTempBtn"
/>
</Grid>
</Grid>
</Grid>
<!--
pumb cooling
-->
<Grid >
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMinHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMinHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMinHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMinHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMinHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMinHelixTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="HELIX JACKET MIN
COOLING TEMP."
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*"
Grid.Row="2"
>
<Grid ColumnDefinitions="Auto,*,Auto"
Tag="pMint">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesMinHelixTempBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="fountainMinTemp" Grid.Column="1"
Text="-05.0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#0000ff"
Margin="0,0,0,0"/>
<TextBlock Grid.Column="1"
Text="°C"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#0000ff"
Margin="0,0,0,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusMinHelixTempBtn"
/>
</Grid>
</Grid>
</Grid>
</StackPanel>
</Border>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="0,10,0,0" Spacing="10">
<!-- A "card" with a label on top, and a row for minus-button / numeric text / plus-button -->
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="180"
>
<StackPanel Spacing="20">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMaxAbsTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMaxAbsTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMaxAbsTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMaxAbsTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMaxAbsTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMaxAbsTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="ABSOLUTE MAX
HEATING TEMP."
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*"
Grid.Row="2"
>
<Grid ColumnDefinitions="Auto,*,Auto"
Tag="aMaxt">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesMaxAbsTempBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="absMaxTemp" Grid.Column="1"
Text="70.0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="0,0,0,0"/>
<TextBlock Grid.Column="1"
Text="°C"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="0,0,0,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusMaxAbsTempBtn"
/>
</Grid>
</Grid>
</Grid>
<!--
pumb cooling
-->
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesAbsMinTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusAbsMinTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesAbsMinTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusAbsMinTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesAbsMinTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusAbsMinTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="ABSOLUTE MIN
COOLING TEMP."
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*"
Grid.Row="2"
>
<Grid ColumnDefinitions="Auto,*,Auto"
Tag="aMint">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesAbsMinTempBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="absMinTemp" Grid.Column="1"
Text="-10.0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#0000ff"
Margin="0,0,0,0"/>
<TextBlock Grid.Column="1"
Text="°C"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#0000ff"
Margin="0,0,0,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusAbsMinTempBtn"
/>
</Grid>
</Grid>
</Grid>
</StackPanel>
</Border>
</StackPanel>
</Grid>
<Grid Grid.Column="1" >
<Grid x:Name="machinePic" Width="450" Height="596" IsVisible="True" Margin="30,0,0,0" >
<Grid.Background >
<ImageBrush Source="/Assets/AdminMachine.png"/>
</Grid.Background>
</Grid>
</Grid>
<Grid Grid.Column="2" RowDefinitions="
*,9*,Auto" Margin="40,0,0,90" >
<Grid Grid.Row="1" >
<!--second card-->
<Border
CornerRadius="12"
Background="White"
Padding="9"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesTankTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusTankTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesTankTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusTankTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesTankTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusTankTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="TANK JACKET MAX HEATING TEMP."
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*" Grid.Row="2" >
<Grid ColumnDefinitions="Auto,*,Auto" Tag="tmt">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesTankTempBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="tankMaxTemp" Grid.Column="1"
Text="60.0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text="°C"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusTankTempBtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
</Grid>
<StackPanel Grid.Row="2" Orientation="Vertical" Margin="0,10,0,0" Spacing="10">
<!-- A "card" with a label on top, and a row for minus-button / numeric text / plus-button -->
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9,5"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesShiftTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusShiftTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesShiftTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusShiftTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesShiftTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusShiftTempBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="TANK AND PUMP
STEADY +SHIFT TEMP."
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="13" Width="142" Margin="0,0,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*" Grid.Row="2" >
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Tag="pht">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesShiftTempBtn"
/>
<StackPanel
Grid.Column="1"
Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="preHeatingTemp" Grid.Column="1"
Text="5"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text=" °C"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#ff0000"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusShiftTempBtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9,5"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHelixDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHelixDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHelixDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHelixDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHelixDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHelixDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="HELIX-ON DELAY AFTER PRE-HEATING"
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="13" Width="142" Margin="0,0,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*" Grid.Row="2" >
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Tag="pd">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesHelixDelayBtn"
/>
<StackPanel
Grid.Column="1"
Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="pumbDelay" Grid.Column="1"
Text="140"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text=" S"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusHelixDelayBtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
<!--second card-->
<Border
CornerRadius="12"
Background="White"
Padding="9,5"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMixerDelaybtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMixerDelaybtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMixerDelaybtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMixerDelaybtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesMixerDelaybtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusMixerDelaybtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="MIXER-ON DELAY AFTER PRE-HEATING"
TextWrapping="Wrap" HorizontalAlignment="Center"
Foreground="#666666"
FontSize="13" Width="142" Margin="0,0,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*" Grid.Row="2">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Tag="md">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesMixerDelaybtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="mixerDelay" Grid.Column="1"
Text="120"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text=" S"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusMixerDelaybtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
</StackPanel>
</Grid>
</Grid>
<!--2ed col (Dots)-->
<Grid Grid.Column="1">
<Grid Width="5" IsVisible="True" Margin="40,0,0,0" >
<Grid.Background >
<ImageBrush Source="/Assets/LineDots.png"/>
</Grid.Background>
</Grid>
</Grid>
<!--3rd col (section two)-->
<Grid Grid.Column="2" Margin="0,20,0,0" RowDefinitions="Auto,*">
<Grid Grid.Row="0" VerticalAlignment="Top" HorizontalAlignment="Center" RowDefinitions="*">
<Grid Grid.Row="0" Width="560" Height="460" IsVisible="True" HorizontalAlignment="Left" Margin="0,10,0,0" RowDefinitions="2.6*,*" >
<Grid.Background >
<ImageBrush Source="/Assets/AdminGraph.png"/>
</Grid.Background>
<Grid Grid.Row="0"></Grid>
<Grid Grid.Row="1">
<StackPanel Orientation="Horizontal" Margin="0,0,60,0" Spacing="0" HorizontalAlignment="Right">
<!-- A "card" with a label on top, and a row for minus-button / numeric text / plus-button -->
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesPouringDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusPouringDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesPouringDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusPouringDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesPouringDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusPouringDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="PRE-POURING PAUSE"
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*" Grid.Row="2">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Tag="pouring">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesPouringDelayBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="pouringPause" Grid.Column="1"
Text="40"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text=" S"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusPouringDelayBtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
<!--second card-->
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="70,0,0,0" Spacing="0" HorizontalAlignment="Left">
<!-- A "card" with a label on top, and a row for minus-button / numeric text / plus-button -->
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHeatingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHeatingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHeatingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHeatingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesHeatingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusHeatingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="POST-HEATING PAUSE"
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid RowDefinitions="*" Grid.Row="2">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Tag="heating">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesHeatingDelayBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="heatingPause" Grid.Column="1"
Text="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text=" S"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusHeatingDelayBtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
<!--second card-->
</StackPanel>
</Grid>
</Grid>
</Grid>
<Grid Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" Margin="0,-3,0,0" Spacing="0" >
<!-- A "card" with a label on top, and a row for minus-button / numeric text / plus-button -->
<!--first card-->
<Border
CornerRadius="12"
Background="White"
Padding="9"
BorderBrush="#DDDDDD"
BorderThickness="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="180"
Height="90">
<Grid>
<Grid Grid.Row="0" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesCoolingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusCoolingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesCoolingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusCoolingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*" >
<Border Grid.Column="0" Background="Transparent"
Tag="minesCoolingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
<Border Grid.Column="1" Background="Transparent"
Tag="plusCoolingDelayBtn"
PointerPressed="changeValue"
Holding="OnLongRecipeClick"
></Border>
</Grid>
<!-- Three rows: label, spacing, buttons row -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<!-- Label row -->
<RowDefinition Height="4"/>
<!-- Spacer -->
<RowDefinition Height="Auto" />
<!-- Buttons + numeric -->
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="3"
Text="POST-COOLING PAUSE"
TextWrapping="Wrap"
HorizontalAlignment="Center"
Foreground="#666666"
FontSize="15" Width="142" Margin="0,-5,0,0"
TextAlignment="Center" ZIndex="-1"/>
<Grid Grid.Row="2" RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Tag="cooling">
<!-- Minus button -->
<Button Grid.Column="0"
Content=""
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="minesCoolingDelayBtn"
/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<!-- Numeric text -->
<TextBlock x:Name="coolingPause" Grid.Column="1"
Text="20"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="16,0,0,0"/>
<TextBlock Grid.Column="1"
Text=" S"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="23.5"
FontWeight="Normal"
Foreground="#231F20"
Margin="0,0,16,0"/>
</StackPanel>
<!-- Plus button -->
<Button Grid.Column="2"
Content="+"
Width="32" Height="32"
Background="#E6E6E6"
BorderThickness="0"
CornerRadius="16"
Foreground="#af196f"
FontSize="25"
FontWeight="Normal"
Click="changeValue"
Holding="OnLongRecipeClick"
x:Name="plusCoolingDelayBtn"
/>
</Grid>
</Grid>
</Grid>
</Border>
</StackPanel>
</Grid>
</Grid>
</Grid>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/Admin.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using AvaloniaApplication1.DataBase;
using DaireApplication.DataBase;
using DaireApplication.Views;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication;
public partial class Admin : UserControl
{
private MainWindow? _mainWindow;
private UserTable? _currentUser;
private MachineTable _machine;
private ConfigrationTable _configration;
private CancellationTokenSource _cancellationTokenSource;
private bool _isLongPress = false;
public Admin()
{
InitializeComponent();
_machine = new MachineTable();
_machine = _machine.ReadMachine();
}
public Admin(MainWindow mainWindow, UserTable currentUser)
{
_currentUser = currentUser;
_mainWindow = mainWindow;
_machine = new MachineTable();
_machine = _machine.ReadMachine();
_configration = new();
InitializeComponent();
setDefaultSettings();
setDafaultValues();
AttachHandlers(_mainWindow.logoBtn, AdvanceSettingsView);
AttachHandlers(_mainWindow.UserName, CloseApplication);
_mainWindow.minimizeBtn.Click += MinimizeButton_Click;
}
public void AttachHandlers(Button button,System.EventHandler<Avalonia.Input.HoldingRoutedEventArgs> func)
{
if (button != null)
{
button.Holding += func;
button.PointerPressed += (sender, e) =>
{
// Simulate a long press on any pointer (mouse or touch)
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type));
};
button.PointerReleased += (sender, e) =>
{
// End simulated long press
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type));
};
}
}
private void MinimizeButton_Click(object? sender, RoutedEventArgs e)
{
_mainWindow.WindowState = Avalonia.Controls.WindowState.Minimized;
}
public static void CloseApplication(object? sender, RoutedEventArgs e)
{
var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
lifetime?.Shutdown(); // This should correctly shut down the application
}
public void AdvanceSettingsView(object? sender, RoutedEventArgs e)
{
if (_mainWindow.ContentArea.Content== this )
{
_mainWindow.ContentArea.Content = new AdvanceSettings(_mainWindow);
}
}
private async void changeValue(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var gridParent = button.Parent as Grid;
var stack = gridParent.Children[1] as StackPanel;
var targetText = stack.Children[0] as TextBlock;
// Handle single click behavior (just increase or decrease by 1)
int currentValue = int.TryParse(targetText.Text, out var value) ? value : 0;
if (gridParent.Tag.ToString() != "pMint" && gridParent.Tag.ToString() != "aMint")
{
if (button.Content.ToString() == "+")
{
targetText.Text = (currentValue + 1).ToString();
}
else
{
if (currentValue>0)
{
targetText.Text = (currentValue - 1).ToString();
}
}
}
else
{
if (button.Content.ToString() == "+")
{
if (currentValue<0)
{
targetText.Text = (currentValue + 1).ToString();
}
}
else
{
targetText.Text = (currentValue - 1).ToString();
}
}
// Perform machine updates based on the tag
MachineTable data = _machine.ReadMachine();
data.Id = _machine.Id;
if (gridParent.Tag.ToString() == "pMaxt")
data.PumbMaxHeat = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pMint")
data.PumbMinHeat = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "tmt")
data.TankMaxHeat = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pd")
data.PumbDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pht")
data.PreHeatingTemp = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "md")
data.MixerDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pouring")
data.PouringDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "cooling")
data.CoolingDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "heating")
data.HeatingDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "aMaxt")
{
data.AbsMaxHeat = int.Parse(targetText.Text);
var allConfigrations = _configration.ReadConfigrations();
foreach (var item in allConfigrations)
{
item.Max = (int)data.AbsMaxHeat;
_configration.UpdateConfigration(item);
}
_mainWindow.sendConfig = true;
}
else if (gridParent.Tag.ToString() == "aMint")
{
data.AbsMinHeat = int.Parse(targetText.Text);
var coolingConfig = _configration.ReadConfigrationById("3");
//var pumbConfig = _configration.ReadConfigrationById("4");
coolingConfig.Min = (int)data.AbsMinHeat;
_configration.UpdateConfigration(coolingConfig);
//pumbConfig.Min = 0;
//_configration.UpdateConfigration(pumbConfig);
_mainWindow.sendConfig = true;
}
_machine.UpdateMachine(data);
_mainWindow._machine = _machine.ReadMachine();
}
else if (sender is Border border)
{
Button button1 = this.FindControl<Button>(border.Tag.ToString());
var gridParent = button1.Parent as Grid;
var stack = gridParent.Children[1] as StackPanel;
var targetText = stack.Children[0] as TextBlock;
// Handle single click behavior (just increase or decrease by 1)
int currentValue = int.TryParse(targetText.Text, out var value) ? value : 0;
if (gridParent.Tag.ToString() != "pMint" && gridParent.Tag.ToString() != "aMint")
{
if (button1.Content.ToString() == "+")
{
targetText.Text = (currentValue + 1).ToString();
}
else
{
if (currentValue > 0)
{
targetText.Text = (currentValue - 1).ToString();
}
}
}
else
{
if (button1.Content.ToString() == "+")
{
if (currentValue < 0)
{
targetText.Text = (currentValue + 1).ToString();
}
}
else
{
targetText.Text = (currentValue - 1).ToString();
}
}
// Perform machine updates based on the tag
MachineTable data = _machine.ReadMachine();
data.Id = _machine.Id;
if (gridParent.Tag.ToString() == "pMaxt")
data.PumbMaxHeat = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pMint")
data.PumbMinHeat = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "tmt")
data.TankMaxHeat = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pd")
data.PumbDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pht")
data.PreHeatingTemp = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "md")
data.MixerDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "pouring")
data.PouringDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "cooling")
data.CoolingDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "heating")
data.HeatingDelay = int.Parse(targetText.Text);
else if (gridParent.Tag.ToString() == "aMaxt")
{
data.AbsMaxHeat = int.Parse(targetText.Text);
var allConfigrations = _configration.ReadConfigrations();
foreach (var item in allConfigrations)
{
item.Max = (int)data.AbsMaxHeat;
_configration.UpdateConfigration(item);
}
_mainWindow.sendConfig = true;
}
else if (gridParent.Tag.ToString() == "aMint")
{
data.AbsMinHeat = int.Parse(targetText.Text);
var coolingConfig = _configration.ReadConfigrationById("3");
//var pumbConfig = _configration.ReadConfigrationById("4");
coolingConfig.Min = (int)data.AbsMinHeat;
_configration.UpdateConfigration(coolingConfig);
//pumbConfig.Min = 0;
//_configration.UpdateConfigration(pumbConfig);
_mainWindow.sendConfig = true;
}
_machine.UpdateMachine(data);
_mainWindow._machine = _machine.ReadMachine();
}
}
// Handle holding event
private async void OnLongRecipeClick(object? sender, RoutedEventArgs e)
{
if (e is HoldingRoutedEventArgs args)
{
if (args.HoldingState == HoldingState.Started)
{
_isLongPress = true;
if (sender is Button button)
{
var gridParent = button.Parent as Grid;
var stack = gridParent.Children[1] as StackPanel;
var targetText = stack.Children[0] as TextBlock;
await ChangeValueRapidly(button.Content.ToString()=="+", targetText); // Start rapid increase
args.Handled = true;
}
else if(sender is Border border)
{
Button button1 = this.FindControl<Button>(border.Tag.ToString());
var gridParent = button1.Parent as Grid;
var stack = gridParent.Children[1] as StackPanel;
var targetText = stack.Children[0] as TextBlock;
await ChangeValueRapidly(button1.Content.ToString() == "+", targetText); // Start rapid increase
args.Handled = true;
}
}
else if (args.HoldingState == HoldingState.Completed || args.HoldingState == HoldingState.Cancelled)
{
_isLongPress = false;
// Stop the rapid value change when the holding is completed
_cancellationTokenSource?.Cancel();
}
}
}
private async Task ChangeValueRapidly(bool isIncrease, TextBlock targetText)
{
// Start rapid value change when the button is held
_cancellationTokenSource?.Cancel(); // Cancel any previous task
_cancellationTokenSource = new CancellationTokenSource();
var token = _cancellationTokenSource.Token;
int currentValue = 0;
while (!token.IsCancellationRequested)
{
currentValue = int.TryParse(targetText.Text, out var value) ? value : 0;
if (targetText.Name!= "fountainMinTemp" && targetText.Name != "absMinTemp")
{
if (isIncrease)
{
targetText.Text = (currentValue + 1).ToString();
}
else
{
if (currentValue>0)
{
targetText.Text = (currentValue -1).ToString();
}
}
}
else
{
if (isIncrease)
{
if (currentValue < 0)
{
targetText.Text = (currentValue + 1).ToString();
}
}
else
{
targetText.Text = (currentValue - 1).ToString();
}
}
await Task.Delay(150); // Change speed here
}
}
private void setDafaultValues()
{
fountainMaxTemp.Text = _machine.PumbMaxHeat.ToString();
tankMaxTemp.Text = _machine.TankMaxHeat.ToString();
pumbDelay.Text = _machine.PumbDelay.ToString();
mixerDelay.Text = _machine.MixerDelay.ToString();
heatingPause.Text = _machine.HeatingDelay.ToString();
coolingPause.Text = _machine.CoolingDelay.ToString();
pouringPause.Text = _machine.PouringDelay.ToString();
fountainMinTemp.Text=_machine.PumbMinHeat.ToString();
absMaxTemp.Text= _machine.AbsMaxHeat.ToString();
absMinTemp.Text= _machine.AbsMinHeat.ToString();
preHeatingTemp.Text= _machine.PreHeatingTemp.ToString();
}
private void setDefaultSettings()
{
_mainWindow.minimizeBtn.IsVisible = true;
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
//_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = false;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
_mainWindow.SoftwareTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = true;
_mainWindow.SettingPolygon.Stroke = Brush.Parse("#A4275D"); ;
_mainWindow.TitleBtn.IsVisible = false;
//_mainWindow.Title.Text = _recipeTable.Name;
//Set Footer
_mainWindow.footerMsg.IsVisible = false;
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = true;
_mainWindow.version.IsVisible = true;
}
}
============================================================
FILE: DaireApplication/Views/UserController/AdvanceSettings.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="DaireApplication.AdvanceSettings"
Background="#b3b3b3"
Width="1280" Height="620">
<UserControl.Styles>
<Style Selector="ComboBox.noArrow">
<Setter Property="Template">
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton x:Name="PART_Button"
Focusable="False"
ClickMode="Press"
IsChecked="{Binding IsDropDownOpen,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}"
Background="#E6E6E6"
Width="210" Height="40">
<Border Background="#E6E6E6"
CornerRadius="8"
Padding="0,0">
<ContentPresenter x:Name="PART_SelectionBoxPresenter"
Content="{TemplateBinding SelectionBoxItem}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
Foreground="#af196f"/>
</Border>
</ToggleButton>
<Popup x:Name="PART_Popup"
PlacementTarget="{Binding #PART_Button}"
Placement="Bottom"
IsOpen="{Binding IsDropDownOpen,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}">
<Border Background="White"
BorderBrush="Gray"
BorderThickness="1">
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TextBlock.lbl">
<Setter Property="Foreground" Value="#000000"/>
</Style>
<Style Selector="ComboBoxItem">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ComboBoxItem:selectable:checked">
<Setter Property="Foreground" Value="#af196f"/>
</Style>
<Style Selector="ComboBoxItem:pointerover">
<Setter Property="Foreground" Value="#af196f"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
</UserControl.Styles>
<Grid RowDefinitions="*">
<!--number keyBoard-->
<Border x:Name="keyBoardPopup"
Background="#80000000"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="False"
ZIndex="50"
PointerPressed="OnPopupOverlayPointerPressed">
<Grid MaxWidth="500" MaxHeight="500" HorizontalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,150,0"
PointerPressed="InnerPopupPointerPressed">
<Border x:Name="PopupControl"
BorderThickness="2"
CornerRadius="10"
Padding="10"
PointerPressed="InnerPopupPointerPressed">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="10">
<!-- Popup Content (Keypad etc.) -->
<Grid IsVisible="True">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="FontSize" Value="50"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="RenderTransform" Value="scale(1.11)"/>
</Style>
</Grid.Styles>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!-- Keypad Buttons -->
<Button Content="1" Grid.Row="0" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="2" Grid.Row="0" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="3" Grid.Row="0" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="4" Grid.Row="1" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="5" Grid.Row="1" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="6" Grid.Row="1" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="7" Grid.Row="2" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="8" Grid.Row="2" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="9" Grid.Row="2" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="." Grid.Row="3" Grid.Column="3" FontSize="54" Background="White" Margin="5" VerticalContentAlignment="Center" Padding="0,0,0,23" Click="OnKeyClick"/>
<Button Content="BACK" Grid.Row="3" Grid.Column="0" FontSize="20" Background="#D3D3D3" Margin="5" Click="OnBackClick"/>
<Button Content="0" Grid.Row="3" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="ENTER" Grid.Row="3" Grid.Column="2" FontSize="20" Background="#A4275D" Foreground="White" Margin="5" Click="EnterClick"/>
</Grid>
</Grid>
</StackPanel>
</Border>
</Grid>
</Border>
<Border Padding="5">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,Auto,*">
<Button x:Name="ignoreFocus" IsVisible="False"></Button>
<!--col 1-->
<Grid Grid.Column="0" >
<Border Width="356" Height="592" CornerRadius="10" Background="#F9F9F9" Margin="5" Padding="5">
<StackPanel Orientation="Vertical" Spacing="6">
<TextBlock HorizontalAlignment="Center" FontSize="20.5" Foreground="#918F90">
INs/OUTs MAPPING
</TextBlock>
<!--IN-->
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">IN-1
</TextBlock>
</Border>
<Image Source="/Assets/greenPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow in" Margin="0" Tag="0"
SelectionChanged="InChanged" >
<ComboBoxItem Content="PEDAL"/>
<ComboBoxItem Content="COVER SENSOR"/>
<ComboBoxItem Content="E-Stop"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
IN-2
</TextBlock>
</Border>
<Image Source="/Assets/greenPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow in" Margin="0" Tag="1"
SelectionChanged="InChanged">
<ComboBoxItem Content="PEDAL"/>
<ComboBoxItem Content="COVER SENSOR"/>
<ComboBoxItem Content="E-Stop"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
IN-3
</TextBlock>
</Border>
<Image Source="/Assets/greenPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow in" Margin="0" Tag="2" SelectionChanged="InChanged" >
<ComboBoxItem Content="PEDAL"/>
<ComboBoxItem Content="COVER SENSOR"/>
<ComboBoxItem Content="E-Stop"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
IN-4
</TextBlock>
</Border>
<Image Source="/Assets/greenPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow in" Margin="0" Tag="3"
SelectionChanged="InChanged">
<ComboBoxItem Content="PEDAL"/>
<ComboBoxItem Content="COVER SENSOR"/>
<ComboBoxItem Content="E-Stop"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
IN-5
</TextBlock>
</Border>
<Image Source="/Assets/greenPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow in" Margin="0" Tag="4"
SelectionChanged="InChanged">
<ComboBoxItem Content="PEDAL"/>
<ComboBoxItem Content="COVER SENSOR"/>
<ComboBoxItem Content="E-Stop"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
IN-6
</TextBlock>
</Border>
<Image Source="/Assets/greenPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow in" Margin="0" Tag="5"
SelectionChanged="InChanged">
<ComboBoxItem Content="PEDAL"/>
<ComboBoxItem Content="COVER SENSOR"/>
<ComboBoxItem Content="E-Stop"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--LOV-->
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
LOV-1
</TextBlock>
</Border>
<Image Source="/Assets/yellowPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow lov" Margin="0" Tag="0"
SelectionChanged="LOVChanged">
<ComboBoxItem Tag="Vibrator Heater" Content="VIBR. HEATER"/>
<ComboBoxItem Tag="Mold Heater" Content="MOLD HEATER"/>
<ComboBoxItem Tag="Alarm" Content="ALARM"/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
LOV-2
</TextBlock>
</Border>
<Image Source="/Assets/yellowPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow lov" Margin="0" Tag="1"
SelectionChanged="LOVChanged">
<ComboBoxItem Tag="Vibrator Heater" Content="VIBR. HEATER"/>
<ComboBoxItem Tag="Mold Heater" Content="MOLD HEATER"/>
<ComboBoxItem Tag="Alarm" Content="ALARM"/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
LOV-3
</TextBlock>
</Border>
<Image Source="/Assets/yellowPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow lov" Margin="0" Tag="2"
SelectionChanged="LOVChanged">
<ComboBoxItem Tag="Vibrator Heater" Content="VIBR. HEATER"/>
<ComboBoxItem Tag="Mold Heater" Content="MOLD HEATER"/>
<ComboBoxItem Tag="Alarm" Content="ALARM"/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
LOV-4
</TextBlock>
</Border>
<Image Source="/Assets/yellowPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow lov" Margin="0" Tag="3"
SelectionChanged="LOVChanged">
<ComboBoxItem Tag="Vibrator Heater" Content="VIBR. HEATER"/>
<ComboBoxItem Tag="Mold Heater" Content="MOLD HEATER"/>
<ComboBoxItem Tag="Alarm" Content="ALARM"/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
LOV-5
</TextBlock>
</Border>
<Image Source="/Assets/yellowPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow lov" Margin="0" Tag="4"
SelectionChanged="LOVChanged">
<ComboBoxItem Tag="Vibrator Heater" Content="VIBR. HEATER"/>
<ComboBoxItem Tag="Mold Heater" Content="MOLD HEATER"/>
<ComboBoxItem Tag="Alarm" Content="ALARM"/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
LOV-6
</TextBlock>
</Border>
<Image Source="/Assets/yellowPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow lov" Margin="0"
Tag="5"
SelectionChanged="LOVChanged">
<ComboBoxItem Tag="Vibrator Heater" Content="VIBR. HEATER"/>
<ComboBoxItem Tag="Mold Heater" Content="MOLD HEATER"/>
<ComboBoxItem Tag="Alarm" Content="ALARM"/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
</StackPanel>
</Border>
</Grid>
<!--col 2-->
<Grid Grid.Column="1" >
<Border Width="356" Height="592" CornerRadius="10" Background="#F9F9F9" Margin="5" Padding="5">
<StackPanel Orientation="Vertical" Spacing="6">
<TextBlock HorizontalAlignment="Center" FontSize="20.5" Foreground="#918F90">
INs/OUTs MAPPING
</TextBlock>
<!--T-->
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
T-1
</TextBlock>
</Border>
<Image Source="/Assets/redPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow T" Margin="0" Tag="8" SelectionChanged="TChanged">
<ComboBoxItem Tag="Tank Bottom Temp" Content="TANK BTN. TEMP."/>
<ComboBoxItem Tag="Tank Wall Temp" Content="TANK WALL TEMP."/>
<ComboBoxItem Tag="Pump Temp" Content="HELIX TEMP."/>
<ComboBoxItem Tag="Fountain Temp" Content="CHOCOLATE TEMP."/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
T-2
</TextBlock>
</Border>
<Image Source="/Assets/redPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow T" Margin="0" Tag="9" SelectionChanged="TChanged">
<ComboBoxItem Tag="Tank Bottom Temp" Content="TANK BTN. TEMP."/>
<ComboBoxItem Tag="Tank Wall Temp" Content="TANK WALL TEMP."/>
<ComboBoxItem Tag="Pump Temp" Content="HELIX TEMP."/>
<ComboBoxItem Tag="Fountain Temp" Content="CHOCOLATE TEMP."/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
T-3
</TextBlock>
</Border>
<Image Source="/Assets/redPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow T" Margin="0" Tag="10" SelectionChanged="TChanged">
<ComboBoxItem Tag="Tank Bottom Temp" Content="TANK BTN. TEMP."/>
<ComboBoxItem Tag="Tank Wall Temp" Content="TANK WALL TEMP."/>
<ComboBoxItem Tag="Pump Temp" Content="HELIX TEMP."/>
<ComboBoxItem Tag="Fountain Temp" Content="CHOCOLATE TEMP."/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
T-4
</TextBlock>
</Border>
<Image Source="/Assets/redPlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow T" Margin="0" Tag="11" SelectionChanged="TChanged">
<ComboBoxItem Tag="Tank Bottom Temp" Content="TANK BTN. TEMP."/>
<ComboBoxItem Tag="Tank Wall Temp" Content="TANK WALL TEMP."/>
<ComboBoxItem Tag="Pump Temp" Content="HELIX TEMP."/>
<ComboBoxItem Tag="Fountain Temp" Content="CHOCOLATE TEMP."/>
<ComboBoxItem Tag="-" Content="-"/>
</ComboBox>
</StackPanel>
<!--HVO-->
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
HVO-1
</TextBlock>
</Border>
<Image Source="/Assets/orangePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow HVO" Margin="0" Tag="0" SelectionChanged="HVOChanged">
<ComboBoxItem Content="Vibrator"/>
<ComboBoxItem Content="Water"/>
<ComboBoxItem Content="Compressor"/>
<ComboBoxItem Content="HELIX Heater"/>
<ComboBoxItem Content="Tank Heater Bottom"/>
<ComboBoxItem Content="Tank Heater Wall"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
HVO-2
</TextBlock>
</Border>
<Image Source="/Assets/orangePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow HVO" Margin="0" Tag="1"
SelectionChanged="HVOChanged">
<ComboBoxItem Content="Vibrator"/>
<ComboBoxItem Content="Water"/>
<ComboBoxItem Content="Compressor"/>
<ComboBoxItem Content="HELIX Heater"/>
<ComboBoxItem Content="Tank Heater Bottom"/>
<ComboBoxItem Content="Tank Heater Wall"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
HVO-3
</TextBlock>
</Border>
<Image Source="/Assets/orangePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow HVO" Margin="0" Tag="2" SelectionChanged="HVOChanged" >
<ComboBoxItem Content="Vibrator"/>
<ComboBoxItem Content="Water"/>
<ComboBoxItem Content="Compressor"/>
<ComboBoxItem Content="HELIX Heater"/>
<ComboBoxItem Content="Tank Heater Bottom"/>
<ComboBoxItem Content="Tank Heater Wall"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
HVO-4
</TextBlock>
</Border>
<Image Source="/Assets/orangePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow HVO" Margin="0" Tag="3" SelectionChanged="HVOChanged">
<ComboBoxItem Content="Vibrator"/>
<ComboBoxItem Content="Water"/>
<ComboBoxItem Content="Compressor"/>
<ComboBoxItem Content="HELIX Heater"/>
<ComboBoxItem Content="Tank Heater Bottom"/>
<ComboBoxItem Content="Tank Heater Wall"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
HVO-5
</TextBlock>
</Border>
<Image Source="/Assets/orangePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow HVO" Margin="0" Tag="4" SelectionChanged="HVOChanged">
<ComboBoxItem Content="Vibrator"/>
<ComboBoxItem Content="Water"/>
<ComboBoxItem Content="Compressor"/>
<ComboBoxItem Content="HELIX Heater"/>
<ComboBoxItem Content="Tank Heater Bottom"/>
<ComboBoxItem Content="Tank Heater Wall"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
HVO-6
</TextBlock>
</Border>
<Image Source="/Assets/orangePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow HVO" Margin="0" Tag="5" SelectionChanged="HVOChanged">
<ComboBoxItem Content="Vibrator"/>
<ComboBoxItem Content="Water"/>
<ComboBoxItem Content="Compressor"/>
<ComboBoxItem Content="HELIX Heater"/>
<ComboBoxItem Content="Tank Heater Bottom"/>
<ComboBoxItem Content="Tank Heater Wall"/>
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--MOT-->
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
MOT-1
</TextBlock>
</Border>
<Image Source="/Assets/bluePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow mot" Margin="0" Tag="0" SelectionChanged="MotChanged">
<ComboBoxItem Tag="Mixer" Content="MIXER MOTOR"/>
<ComboBoxItem Tag="HELIX" Content="HELIX MOTOR"/>
<ComboBoxItem Tag="" Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
MOT-2
</TextBlock>
</Border>
<Image Source="/Assets/bluePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow mot" Margin="0" Tag="1" SelectionChanged="MotChanged" >
<ComboBoxItem Tag="Mixer" Content="MIXER MOTOR"/>
<ComboBoxItem Tag="HELIX" Content="HELIX MOTOR"/>
<ComboBoxItem Tag="" Content="-"/>
</ComboBox>
</StackPanel>
</StackPanel>
</Border>
</Grid>
<!--col 3-->
<Grid Grid.Column="2" ZIndex="100">
<StackPanel Orientation="Vertical" Margin="0,9" Spacing="5" ZIndex="100"
>
<Border Width="356" Height="132" CornerRadius="10" Background="#F9F9F9" Padding="5" ZIndex="100">
<StackPanel Orientation="Vertical" Spacing="6">
<TextBlock HorizontalAlignment="Center" FontSize="20.5" Foreground="#918F90">
INs/OUTs MAPPING
</TextBlock>
<!--AN-->
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
AN-1
</TextBlock>
</Border>
<Image Source="/Assets/purplePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow" Margin="0" SelectedIndex="0" >
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
<!--line-->
<StackPanel Orientation="Horizontal">
<Border Width="85" Height="40" Background="#E6E6E6" CornerRadius="5">
<TextBlock Classes="lbl" FontSize="22.5" VerticalAlignment="Center" HorizontalAlignment="Center">
AN-2
</TextBlock>
</Border>
<Image Source="/Assets/purplePlug.png" Width="50" Height="20"></Image>
<!-- Apply the #PedalComboBox style by giving it that Name -->
<ComboBox Classes="noArrow" Margin="0" SelectedIndex="0" >
<ComboBoxItem Content="-"/>
</ComboBox>
</StackPanel>
</StackPanel>
</Border>
<!--Values-->
<Border
Width="222"
Height="450"
Background="#f9f9f9"
CornerRadius="10"
Padding="5"
Margin="5"
HorizontalAlignment="Left"
ZIndex="100">
<StackPanel
Orientation="Vertical"
Spacing="6">
<!--VALUES-->
<TextBlock
HorizontalAlignment="Center"
FontSize="20.5"
Foreground="#918f90">VALUES</TextBlock>
<!--row 1-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5">
<Button Padding="5" Background="Transparent"
Width="210" Height="40" Click="extPowerClick">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">Ext Power?</TextBlock>
<TextBlock
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f"
x:Name="extPowerValue">Yes</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 2-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button Background="Transparent"
Padding="0,5,5,0"
Width="210"
Height="40"
Click="supplyButtonClick">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">
Phases
</TextBlock>
<TextBlock
x:Name="phasesNumberValue"
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f">3-Phases</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 3-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button Background="Transparent"
Padding="0,5,5,0"
Width="210"
Height="40"
Click="voltageButtonClick">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">
Voltage
</TextBlock>
<TextBlock
x:Name="voltageNumberValue"
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f">220 V</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 4-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button Background="Transparent"
Width="210"
Height="40"
Padding="0,5,5,0"
Click="gridButtonClick">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">GRID FREQ</TextBlock>
<TextBlock
x:Name="gridValue"
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f">50Hz</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 5-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" >
<Button Width="210"
Height="40"
Background="Transparent"
Padding="5"
x:Name="i_neut"
Click="ShowNumberKeyBoard">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">
MAX I-NEUT
</TextBlock>
<TextBlock
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f"
x:Name="i_neutValue"
>12</TextBlock>
<TextBlock
Grid.Column="2"
FontSize="22.5"
Foreground="#af196f"
>A</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 6-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5">
<Button Width="210"
Height="40"
Padding="5"
Background="Transparent"
x:Name="i_mot1"
Click="ShowNumberKeyBoard">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">
MAX I-MOT1
</TextBlock>
<TextBlock
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f"
x:Name="i_mot1Value"
>3</TextBlock>
<TextBlock
Grid.Column="2"
FontSize="22.5"
Foreground="#af196f"
>A</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 7-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5">
<Button Width="210"
Height="40"
Padding="5"
Background="Transparent"
x:Name="i_mot2"
Click="ShowNumberKeyBoard">
<Grid RowDefinitions="*">
<Grid
Grid.Row="0"
ColumnDefinitions="*,Auto,Auto">
<TextBlock
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20">
MAX I-MOT2
</TextBlock>
<TextBlock
Grid.Column="1"
FontSize="22.5"
Foreground="#af196f"
x:Name="i_mot2Value"
>3</TextBlock>
<TextBlock
Grid.Column="2"
FontSize="22.5"
Foreground="#af196f"
>A</TextBlock>
</Grid>
</Grid>
</Button>
</Border>
<!--row 8-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5">
</Border>
<!--row 9-->
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Content="TEMPs SETTINGS"
Click="showPidPopUp">
</Button>
</Border>
</StackPanel>
</Border>
</StackPanel>
</Grid>
<!--col 4-->
<Grid Grid.Column="3"></Grid>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="innerPidPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnIgnoreInnerPidPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="header" Tag="0" Text="PID T-1 FACTORS"
FontSize="20"
FontWeight="Bold"
Foreground="#A4275D"
Margin="0,0,0,8" />
<StackPanel Spacing="5">
<!-- Add button styles at the top of the StackPanel -->
<StackPanel.Styles>
<Style Selector="Button.circleButton">
<Setter Property="Width" Value="32"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Background" Value="#E6E6E6"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="CornerRadius" Value="16"/>
<Setter Property="Foreground" Value="#af196f"/>
<Setter Property="FontSize" Value="25"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}"
FontWeight="{TemplateBinding FontWeight}"
TextAlignment="Center"
Margin="0,0,0,2"/>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
</StackPanel.Styles>
<!-- KP Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KP: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="kpSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KpMinusClick"
x:Name="kpMinusBtn"/>
<Slider Grid.Column="1"
x:Name="kpSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KpSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KpPlusClick"
x:Name="kpPlusBtn"/>
</Grid>
<!-- KI Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KI: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="kiSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KiMinusClick"
x:Name="kiMinusBtn"/>
<Slider Grid.Column="1"
x:Name="kiSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KiSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KiPlusClick"
x:Name="kiPlusBtn"/>
</Grid>
<!-- KD Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KD: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="kdSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KdMinusClick"
x:Name="kdMinusBtn"/>
<Slider Grid.Column="1"
x:Name="kdSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KdSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KdPlusClick"
x:Name="kdPlusBtn"/>
</Grid>
<!-- KL Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KL: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="klSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KlMinusClick"
x:Name="klMinusBtn"/>
<Slider Grid.Column="1"
x:Name="klSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KlSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KlPlusClick"
x:Name="klPlusBtn"/>
</Grid>
<TextBlock Text="PID Activation Threshold (°C)"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"
/>
<Border Name="heatConRangeBorder" >
<TextBox Name="heatConRange"
KeyUp="OnKeyUp"></TextBox>
</Border>
<TextBlock Text="Fast Cooling Threshold (°C)"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"
/>
<Border Name="fcThresholdBorder" >
<TextBox Name="fcThreshold"
KeyUp="OnKeyUp"></TextBox>
</Border>
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<!-- yes Button -->
<Button
x:Name="okBtn"
Content="OK"
FontSize="16"
Padding="10,5"
Click="YesBtnClick"
Width="75"
Foreground="White"
HorizontalContentAlignment="Center">
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#A4275D"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
<!-- No Button -->
<Button
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Width="75"
Click="OnIgnoreInnerPidPopupOverlayPointerPressed">
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="pidPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnIgnorePidPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="pidHeader" Text="Choose PID FACTOR"
FontSize="20"
FontWeight="Bold"
Foreground="#A4275D"
HorizontalAlignment="Center"
Margin="0,0,0,8" />
<StackPanel Spacing="15">
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Content="T-1 SETTINGS"
Tag="1"
Click="showInnerPid">
</Button>
</Border>
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Tag="2"
Content="T-2 SETTINGS"
Click="showInnerPid">
</Button>
</Border>
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Tag="3"
Content="T-3 SETTINGS"
Click="showInnerPid">
</Button>
</Border>
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Tag="4"
Content="T-4 SETTINGS"
Click="showInnerPid">
</Button>
</Border>
</StackPanel>
<!-- Button Panel -->
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/AdvanceSettings.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using AvaloniaApplication1.DataBase;
using DaireApplication.DataBase;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using DynamicData;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static DaireApplication.Views.MainWindow;
namespace DaireApplication;
public partial class AdvanceSettings : UserControl
{
public Mapping _mapping;
public ConfigrationTable _configration;
public List<Mapping> _mappingRecordes;
MainWindow _mainWindow;
private Process? _keyboardProcess;
public ErrorSettingsTable _error = new();
TextBlock targetText = new TextBlock();
float oldValue = 0;
bool _isDiag;
bool _isSoftware;
public AdvanceSettings(MainWindow mainWindow,bool isDiag=false,bool isSoftware=false)
{
InitializeComponent();
_mainWindow = mainWindow;
_mapping = new Mapping();
_mappingRecordes = _mapping.ReadMappings();
_configration = new();
_isDiag = isDiag;
_isSoftware = isSoftware;
setDefaultValues();
// Remove the old text box event handlers since we're using sliders now
// kp.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel);
// ki.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel);
// kd.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel);
// kl.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel);
fcThreshold.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
heatConRange.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
// Remove the old border event handlers since we're using sliders now
// kpBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
// kiBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
// kdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
// klBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
fcThresholdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
heatConRangeBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
AttachHandlers(_mainWindow.UserName, CloseApplication);
setDefaultSettings();
}
public AdvanceSettings()
{
InitializeComponent();
}
public void AttachHandlers(Button button, System.EventHandler<Avalonia.Input.HoldingRoutedEventArgs> func)
{
if (button != null)
{
button.Holding += func;
button.PointerPressed += (sender, e) =>
{
// Simulate a long press on any pointer (mouse or touch)
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type));
};
button.PointerReleased += (sender, e) =>
{
// End simulated long press
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type));
};
}
}
public static void CloseApplication(object? sender, RoutedEventArgs e)
{
var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
lifetime?.Shutdown(); // This should correctly shut down the application
}
private void HVOChanged(object? sender, RoutedEventArgs e)
{
if (sender is ComboBox comboBox)
{
if (comboBox.SelectedItem is ComboBoxItem selectedItem)
{
// Get the displayed content
//HVO
var result= _mappingRecordes.FindAll(x => x.Address == "1" && x.IsRead==false).Find(c=>c.Name==selectedItem.Content.ToString());
if (result!=null)
{
if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())))
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == false && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord!=null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
}
result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString()));
_mapping.UpdateMapping(result);
setDefaultValues();
}
}
else
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == false && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
}
}
_mappingRecordes = _mapping.ReadMappings();
_mainWindow._mapping = _mappingRecordes;
var configrations = _configration.ReadConfigrations();
var compressor = _mappingRecordes.Find(x => x.Name == "Compressor");
var water = _mappingRecordes.Find(x => x.Name == "Water");
if (compressor != null && water != null)
{
if (compressor.BitNumbers.Count > 0 )
{
configrations[2].FC_out = compressor.BitNumbers.Concat(water.BitNumbers).ToList();
configrations[3].FC_out = compressor.BitNumbers.Concat(water.BitNumbers).ToList();
}
else
{
configrations[2].FC_out = [-1];
configrations[3].FC_out = [-1];
}
if (water.BitNumbers.Count > 0)
{
configrations[2].SC_out = water.BitNumbers;
configrations[3].SC_out = water.BitNumbers;
}
else
{
configrations[2].SC_out = [-1];
configrations[3].SC_out = [-1];
}
_configration.UpdateConfigration(configrations[2]);
_configration.UpdateConfigration(configrations[3]);
}
foreach (var item in configrations)
{
var namedMap = _mappingRecordes.Find(x => x.Name == item.name);
if (namedMap!=null)
{
if (namedMap.BitNumbers.Count>0)
{
item.H_out = namedMap.BitNumbers;
if (namedMap.Name!= "HELIX Heater")
{
item.FC_out = [-1];
item.SC_out = [-1];
}
_configration.UpdateConfigration(item);
}
else
{
item.H_out =[-1];
if (namedMap.Name != "HELIX Heater")
{
item.FC_out = [-1];
item.SC_out = [-1];
}
_configration.UpdateConfigration(item);
}
}
else
{
}
}
configrations[3].H_out = configrations[2].H_out;
_configration.UpdateConfigration(configrations[3]);
_mainWindow.sendConfig = true;
}
}
}
private void TChanged(object? sender, RoutedEventArgs e)
{
if (sender is ComboBox comboBox)
{
if (comboBox.SelectedItem is ComboBoxItem selectedItem)
{
// Get the displayed content
//HVO
var result = _mappingRecordes.Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower());
if (result != null)
{
if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())))
{
var oldRecord = _mappingRecordes.Find(x => x.Name.EndsWith("Temp") && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
}
result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString()));
_mapping.UpdateMapping(result);
setDefaultValues();
}
}
else
{
var oldRecord = _mappingRecordes.Find(x => x.Name.EndsWith("Temp") && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
setDefaultValues();
}
}
_mappingRecordes = _mapping.ReadMappings();
_mainWindow._mapping = _mappingRecordes;
}
}
}
private void LOVChanged(object? sender, RoutedEventArgs e)
{
if (sender is ComboBox comboBox)
{
if (comboBox.SelectedItem is ComboBoxItem selectedItem)
{
var result = _mappingRecordes.FindAll(x => x.Address == "2").Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower());
if (result != null)
{
if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())))
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "2" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
}
result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString()));
_mapping.UpdateMapping(result);
setDefaultValues();
}
}
else
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "2" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
setDefaultValues();
}
}
_mappingRecordes = _mapping.ReadMappings();
_mainWindow._mapping = _mappingRecordes;
}
}
}
private void InChanged(object? sender, RoutedEventArgs e)
{
if (sender is ComboBox comboBox)
{
if (comboBox.SelectedItem is ComboBoxItem selectedItem)
{
// Get the displayed content
//HVO
var result = _mappingRecordes.FindAll(x => x.Address == "1" &&x.IsRead==true).Find(c => c.Name.ToLower() == selectedItem.Content.ToString().ToLower());
if (result != null)
{
if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())))
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == true && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
}
result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString()));
_mapping.UpdateMapping(result);
setDefaultValues();
}
}
else
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == true && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
setDefaultValues();
}
}
_mappingRecordes = _mapping.ReadMappings();
_mainWindow._mapping = _mappingRecordes;
}
}
}
private void MotChanged(object? sender, RoutedEventArgs e)
{
if (sender is ComboBox comboBox)
{
if (comboBox.SelectedItem is ComboBoxItem selectedItem)
{
var result = _mappingRecordes.FindAll(x => x.Address == "3").Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower());
if (result != null)
{
if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())))
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "3" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
}
result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString()));
_mapping.UpdateMapping(result);
setDefaultValues();
}
}
else
{
var oldRecord = _mappingRecordes.Find(x => x.Address == "3" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString())));
if (oldRecord != null)
{
_mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString()));
setDefaultValues();
}
}
_mappingRecordes = _mapping.ReadMappings();
_mainWindow._mapping = _mappingRecordes;
}
}
}
private (string? fileName, string args) GetKeyboardCommand()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return ("osk.exe", "");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return ("onboard", ""); // or "florence", "matchbox-keyboard"
return (null, "");
}
private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e)
{
if (_keyboardProcess is { HasExited: false })
return;
var (fileName, args) = GetKeyboardCommand();
if (fileName is null)
return;
_keyboardProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = args,
UseShellExecute = true,
WorkingDirectory = "/usr/bin"
},
EnableRaisingEvents = true
};
try
{
_keyboardProcess.Start();
Dispatcher.UIThread.Post(() =>
{
if (sender is Border border)
{
var textbox = border.Child as TextBox;
textbox.SelectionStart = 0;
textbox.SelectionEnd = textbox.Text?.Length ?? 0;
}
});
}
catch
{
// fail silently if keyboard not found
}
}
private async void OnIgnoreInnerPidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
innerPidPopupOverlay.IsVisible = false;
pidPopupOverlay.IsVisible = true;
}
private async void OnIgnorePidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
pidPopupOverlay.IsVisible = false;
}
private async void YesBtnClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var configration = _configration.ReadConfigrationById(header.Tag.ToString());
if (configration!=null)
{
// Read values from sliders instead of text boxes
configration.kp = (int)kpSlider.Value;
configration.ki = (int)kiSlider.Value;
configration.kd = (int)kdSlider.Value;
configration.kl = (int)klSlider.Value;
if (string.IsNullOrEmpty(fcThreshold.Text))
{
configration.FC_Threshold = 0;
}
else
{
configration.FC_Threshold = float.Parse(fcThreshold.Text);
}
if (string.IsNullOrEmpty(heatConRange.Text))
{
configration.HeatConRange = 1.0F;
}
else
{
if (float.TryParse(heatConRange.Text, out float value))
{
if (value<1.0)
{
configration.HeatConRange = 1.0F;
}
else
{
configration.HeatConRange = float.Parse(heatConRange.Text);
}
}
else
{
configration.HeatConRange = 1.0F;
}
}
_configration.UpdateConfigration(configration);
_mainWindow.sendConfig = true;
CloseKeyboard();
innerPidPopupOverlay.IsVisible = false;
pidPopupOverlay.IsVisible = true;
}
}
}
private async void showPidPopUp(object? sender, RoutedEventArgs e)
{
pidPopupOverlay.IsVisible = true;
}
private async void showInnerPid(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var configratipn = _configration.ReadConfigrationById(button.Tag.ToString());
pidPopupOverlay.IsVisible = false;
header.Text = button.Content.ToString();
header.Tag = button.Tag;
// Set slider values instead of text box values
kpSlider.Value = configratipn.kp;
kiSlider.Value = configratipn.ki;
kdSlider.Value = configratipn.kd;
klSlider.Value = configratipn.kl;
// Update the display values
kpSliderValue.Text = configratipn.kp.ToString();
kiSliderValue.Text = configratipn.ki.ToString();
kdSliderValue.Text = configratipn.kd.ToString();
klSliderValue.Text = configratipn.kl.ToString();
fcThreshold.Text = configratipn.FC_Threshold.ToString("0.0");
heatConRange.Text = configratipn.HeatConRange.ToString("0.0");
innerPidPopupOverlay.IsVisible = true;
}
}
// KP Slider and Button Event Handlers
private void KpSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (kpSliderValue != null && sender is Slider slider)
{
kpSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KpMinusClick(object? sender, RoutedEventArgs e)
{
if (kpSlider.Value > kpSlider.Minimum)
{
kpSlider.Value--;
}
}
private void KpPlusClick(object? sender, RoutedEventArgs e)
{
if (kpSlider.Value < kpSlider.Maximum)
{
kpSlider.Value++;
}
}
// KI Slider and Button Event Handlers
private void KiSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (kiSliderValue != null && sender is Slider slider)
{
kiSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KiMinusClick(object? sender, RoutedEventArgs e)
{
if (kiSlider.Value > kiSlider.Minimum)
{
kiSlider.Value--;
}
}
private void KiPlusClick(object? sender, RoutedEventArgs e)
{
if (kiSlider.Value < kiSlider.Maximum)
{
kiSlider.Value++;
}
}
// KD Slider and Button Event Handlers
private void KdSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (kdSliderValue != null && sender is Slider slider)
{
kdSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KdMinusClick(object? sender, RoutedEventArgs e)
{
if (kdSlider.Value > kdSlider.Minimum)
{
kdSlider.Value--;
}
}
private void KdPlusClick(object? sender, RoutedEventArgs e)
{
if (kdSlider.Value < kdSlider.Maximum)
{
kdSlider.Value++;
}
}
// KL Slider and Button Event Handlers
private void KlSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (klSliderValue != null && sender is Slider slider)
{
klSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KlMinusClick(object? sender, RoutedEventArgs e)
{
if (klSlider.Value > klSlider.Minimum)
{
klSlider.Value--;
}
}
private void KlPlusClick(object? sender, RoutedEventArgs e)
{
if (klSlider.Value < klSlider.Maximum)
{
klSlider.Value++;
}
}
private void OnTextInput(object? sender, TextInputEventArgs e)
{
if (sender is TextBox textBox)
{
string newText = textBox.Text + e.Text;
if (!Regex.IsMatch(newText, @"^\d*\.?\d*$"))
{
e.Handled = true;
}
}
}
private void OnTextInputOnlyInteager(object? sender, TextInputEventArgs e)
{
if (sender is TextBox textBox)
{
string newText = textBox.Text + e.Text;
if (!Regex.IsMatch(newText, @"^\d*$"))
{
e.Handled = true;
}
}
}
private async void gridButtonClick(object? sender, RoutedEventArgs e)
{
var error = _error.ReadErrorSettings()[0];
if (gridValue.Text == "50Hz")
{
error.gridFreq = 60;
_error.UpdateError(error);
setDefaultValues();
}
else
{
error.gridFreq = 50;
_error.UpdateError(error);
setDefaultValues();
}
}
private async void supplyButtonClick(object? sender, RoutedEventArgs e)
{
var error = _error.ReadErrorSettings()[0];
int bit = 11;
if (phasesNumberValue.Text == "3-Phases")
{
error.phaseNumber = 1;
_error.UpdateError(error);
setDefaultValues();
_mainWindow.holdingRegister.resetError |= (ushort)(1 << bit);
}
else
{
error.phaseNumber = 3;
_error.UpdateError(error);
_mainWindow.holdingRegister.resetError &= (ushort)~(1 << bit);
setDefaultValues();
}
await _mainWindow.WriteToSerialAsync("supplyButtonClick");
}
private async void voltageButtonClick(object? sender, RoutedEventArgs e)
{
var error = _error.ReadErrorSettings()[0];
int bit = 12;
if (voltageNumberValue.Text.Contains("220"))
{
error.phaseVoltage = 110;
_error.UpdateError(error);
setDefaultValues();
_mainWindow.holdingRegister.resetError |= (ushort)(1 << bit);
}
else
{
error.phaseVoltage =220;
_error.UpdateError(error);
_mainWindow.holdingRegister.resetError &= (ushort)~(1 << bit);
setDefaultValues();
}
await _mainWindow.WriteToSerialAsync("voltageButtonClick");
}
private async void extPowerClick(object? sender, RoutedEventArgs e)
{
var error = _error.ReadErrorSettings()[0];
if (extPowerValue.Text == "Yes")
{
error.extPower = false;
_error.UpdateError(error);
setDefaultValues();
}
else
{
error.extPower = true;
_error.UpdateError(error);
setDefaultValues();
}
}
private void setDefaultValues()
{
_mappingRecordes = _mapping.ReadMappings();
var allHVOComboBox= this.GetLogicalDescendants()
.OfType<ComboBox>()
.Where(cb => cb.Classes.Contains("HVO"))
.ToList();
//HVO
for (int i = 0; i < allHVOComboBox.Count; i++)
{
var result = _mappingRecordes.FindAll(x => x.Address == "1" && x.IsRead==false ).Find(c => c.BitNumbers.Contains(int.Parse(allHVOComboBox[i].Tag.ToString())));
if (result != null)
{
allHVOComboBox[i].SelectedIndex = result.Id - 11;
}
else
{
allHVOComboBox[i].SelectedIndex = 6;
}
}
// IN
var allINComboBox = this.GetLogicalDescendants()
.OfType<ComboBox>()
.Where(cb => cb.Classes.Contains("in"))
.ToList();
for (int i = 0; i < allINComboBox.Count; i++)
{
var result = _mappingRecordes.FindAll(x => x.Address == "1"&&x.IsRead==true).Find(c => c.BitNumbers.Contains(int.Parse(allINComboBox[i].Tag.ToString())));
if (result != null)
{
allINComboBox[i].SelectedIndex = result.Id - 1;
}
else
{
allINComboBox[i].SelectedIndex = 3;
}
}
//LOV
var allLOVComboBox = this.GetLogicalDescendants()
.OfType<ComboBox>()
.Where(cb => cb.Classes.Contains("lov"))
.ToList();
for (int i = 0; i < allLOVComboBox.Count; i++)
{
var result = _mappingRecordes.FindAll(x => x.Address == "2" && x.IsRead == false).Find(c => c.BitNumbers.Contains(int.Parse(allLOVComboBox[i].Tag.ToString())));
if (result != null)
{
allLOVComboBox[i].SelectedIndex = result.Id - 8;
}
else
{
allLOVComboBox[i].SelectedIndex = 3;
}
}
// T
var allTComboBox = this.GetLogicalDescendants()
.OfType<ComboBox>()
.Where(cb => cb.Classes.Contains("T"))
.ToList();
for (int i = 0; i < allTComboBox.Count; i++)
{
var result = _mappingRecordes.FindAll(x => x.Name.EndsWith("Temp")).Find(c => c.BitNumbers.Contains(int.Parse(allTComboBox[i].Tag.ToString())));
if (result != null)
{
allTComboBox[i].SelectedIndex = result.Id - 4;
}
else
{
allTComboBox[i].SelectedIndex = 5;
}
}
// MOT
var allMotComboBox = this.GetLogicalDescendants()
.OfType<ComboBox>()
.Where(cb => cb.Classes.Contains("mot"))
.ToList();
for (int i = 0; i < allMotComboBox.Count; i++)
{
var result = _mappingRecordes.FindAll(x => x.Address == "3" && x.IsRead==false).Find(c => c.BitNumbers.Contains(int.Parse(allMotComboBox[i].Tag.ToString())));
if (result != null)
{
allMotComboBox[i].SelectedIndex = result.Id - 17;
}
else
{
allMotComboBox[i].SelectedIndex = 2;
}
}
var error = _error.ReadErrorSettings()[0];
phasesNumberValue.Text = $"{error.phaseNumber}-Phases";
voltageNumberValue.Text = $"{error.phaseVoltage} V";
gridValue.Text = $"{error.gridFreq}Hz";
extPowerValue.Text = error.extPower ? "Yes" : "No";
var config = _configration.ReadConfigrations()[0];
i_neutValue.Text = config.i_neut.ToString("0.0");
i_mot1Value.Text = config.i_mot1.ToString("0.0");
i_mot2Value.Text = config.i_mot2.ToString("0.0");
}
private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e)
{
targetText.Text = oldValue.ToString("0.0");
keyBoardPopup.IsVisible = false;
}
private void OnKeyClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (button.Content == ".")
{
if (Char.IsDigit(targetText.Text[0]) && !targetText.Text.Contains(button.Content.ToString()))
{
targetText.Text += button.Content;
}
}
else
{
targetText.Text += button.Content;
if (float.Parse(targetText.Text) > 20.0)
{
targetText.Text = "20.0";
}
}
}
}
private void OnBackClick(object? sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(targetText.Text))
{
// Remove the last character from the text box
targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1);
//number = number.Remove(number.Length - 1);
}
}
private void EnterClick(object? sender, RoutedEventArgs e)
{
var config = _configration.ReadConfigrations()[0];
if (targetText.Name== "i_mot2Value")
{
config.i_mot2 = float.Parse(targetText.Text);
}
else if (targetText.Name == "i_mot1Value")
{
config.i_mot1 = float.Parse(targetText.Text);
}
else
{
config.i_neut = float.Parse(targetText.Text);
}
_configration.UpdateConfigration(config);
setDefaultValues();
_mainWindow.sendConfig = true;
keyBoardPopup.IsVisible = false;
}
private void ShowNumberKeyBoard(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (button.Name=="i_mot2")
{
targetText = i_mot2Value;
}
else if (button.Name == "i_mot1")
{
targetText = i_mot1Value;
}
else if (button.Name== "i_neut")
{
targetText = i_neutValue;
}
oldValue = float.Parse(targetText.Text);
targetText.Text = "";
keyBoardPopup.IsVisible = true;
}
}
private void OnKeyUp(object? sender, KeyEventArgs e)
{
if (sender is TextBox textBox)
{
if (textBox != null && float.TryParse(textBox.Text, out float value))
{
if (textBox.Name== "heatConRange")
{
if (value > 25.0)
{
textBox.Text = "25.0";
}
}
else
{
if (value > 100)
{
textBox.Text = "100";
}
}
// Check if the value exceeds 100 and reset to 100 if necessary.
}
}
}
private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e)
{
e.Handled = true;
}
private void CloseKeyboard()
{
try
{
if (_keyboardProcess != null)
{
// Kill the keyboard process
_keyboardProcess.Kill();
_keyboardProcess.Dispose();
_keyboardProcess = null;
// Force kill any remaining keyboard processes
var processKill = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "killall",
Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards
UseShellExecute = false,
CreateNoWindow = true
}
};
processKill.Start();
processKill.WaitForExit(1000);
processKill.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error closing keyboard: {ex.Message}");
}
}
private void setDefaultSettings()
{
_mainWindow.minimizeBtn.IsVisible = false;
var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel;
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = false;
_mainWindow.RecipeEditTrack.IsVisible = false;
if (_isDiag||_isSoftware)
{
if (_isDiag)
{
_mainWindow.DiagnosticsTrack.IsVisible = true;
_mainWindow.DiagnosticsPolygon.Stroke = Avalonia.Media.Brushes.Black;
}
else if (_isSoftware)
{
_mainWindow.SoftwareTrack.IsVisible = true;
_mainWindow.SoftwarePolygon.Stroke = Avalonia.Media.Brushes.Black;
}
_mainWindow.SettingTrack.IsVisible = false;
}
else
{
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.SoftwareTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = true;
_mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black;
}
// Remove the button from its current position
stackPanel.Children.Remove(_mainWindow.AdvanceSettingsTrack);
// Add it back at the end of the StackPanel
stackPanel.Children.Add(_mainWindow.AdvanceSettingsTrack);
_mainWindow.AdvanceSettingsTrack.IsVisible = true;
_mainWindow.AdvanceSettingsPolygon.Stroke = Brush.Parse("#A4275D");
_mainWindow.TitleBtn.IsVisible = true;
_mainWindow.Title.Text = "DR-62664A";
//Set Footer
_mainWindow.footerMsg.IsVisible = true;
_mainWindow.footerMsg.Text = "Map Inputs And Outputs, And Set The Board Internal Values";
_mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D");
_mainWindow.footer.Background = Brush.Parse("#f2f2f2");
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = false;
}
}
============================================================
FILE: DaireApplication/Views/UserController/Diagnostics.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="1280"
Height="620"
Background="#B3B3B3"
x:Class="DaireApplication.Diagnostics">
<Grid RowDefinitions="*" Margin="0,5">
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,1.3*">
<!--left col-->
<Grid Grid.Column="0" RowDefinitions="0.9*,4.6*,Auto" Margin="0,0,5,0" HorizontalAlignment="Right" Background=""
>
<Grid Grid.Row="0" >
</Grid>
<!-- Right arrow -->
<Grid Height="14" Width="50" VerticalAlignment="Bottom" Margin="-35,0,0,5">
<Grid.Background>
<ImageBrush Source="/Assets/RightArrow.png"/>
</Grid.Background>
</Grid>
<StackPanel Grid.Row="1" Spacing="20">
<Border Width="111" Height="290" CornerRadius="5" Padding="10,5" VerticalAlignment="Top" Background="#F9F9F9"
Margin="-45,0,0,0" >
<StackPanel Orientation="Vertical">
<!-- Top label -->
<TextBlock Text="SIGNALS"
Foreground="#A4A2A3"
FontSize="16.5"
HorizontalAlignment="Center"
/>
<TextBlock Text="INPUTS"
Foreground="#A4A2A3"
FontSize="16.5"
HorizontalAlignment="Center"
Margin="0"
/>
<StackPanel Orientation="Vertical" Spacing="7">
<!-- First row: ACTIVE -->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5">
<Button Width="99" Height="33" Background="#E6E6E6" Padding="5">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Classes="in" Tag="0">
<TextBlock
Grid.Column="0"
Text="PASSIVE"
Foreground="#918f90"
FontSize="19"
FontWeight="Light"
VerticalAlignment="Center"
>
</TextBlock>
<Border Grid.Column="1"
Width="5"
Height="27"
CornerRadius="1"
Background="#666666"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5">
<Button Width="99" Height="33" Background="#E6E6E6" Padding="5">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Classes="in" Tag="1">
<TextBlock
Grid.Column="0"
Text="PASSIVE"
Foreground="#918f90"
FontSize="19"
FontWeight="Light"
VerticalAlignment="Center"
>
</TextBlock>
<Border Grid.Column="1"
Width="5"
Height="27"
CornerRadius="1"
Background="#666666"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- Third row: PASSIVE -->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5">
<Button Width="99" Height="33" Background="#E6E6E6" Padding="5">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Classes="in" Tag="2">
<TextBlock
Grid.Column="0"
Text="PASSIVE"
Foreground="#918f90"
FontSize="19"
FontWeight="Light"
VerticalAlignment="Center"
>
</TextBlock>
<Border Grid.Column="1"
Width="5"
Height="27"
CornerRadius="1"
Background="#666666"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- Fourth row: PASSIVE -->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5">
<Button Width="99" Height="33" Background="#E6E6E6" Padding="5">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Classes="in" Tag="3">
<TextBlock
Grid.Column="0"
Text="PASSIVE"
Foreground="#918f90"
FontSize="19"
FontWeight="Light"
VerticalAlignment="Center"
>
</TextBlock>
<Border Grid.Column="1"
Width="5"
Height="27"
CornerRadius="1"
Background="#666666"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- Fifth row: ACTIVE -->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5">
<Button Width="99" Height="33" Background="#E6E6E6" Padding="5">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Classes="in" Tag="4">
<TextBlock
Grid.Column="0"
Text="PASSIVE"
Foreground="#918f90"
FontSize="19"
FontWeight="Light"
VerticalAlignment="Center"
>
</TextBlock>
<Border Grid.Column="1"
Width="5"
Height="27"
CornerRadius="1"
Background="#666666"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- Sixth row: ACTIVE -->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5">
<Button Width="99" Height="33" Background="#E6E6E6" Padding="5">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="*,Auto" Classes="in" Tag="5">
<TextBlock
Grid.Column="0"
Text="PASSIVE"
Foreground="#918f90"
FontSize="19"
FontWeight="Light"
VerticalAlignment="Center"
>
</TextBlock>
<Border Grid.Column="1"
Width="5"
Height="27"
CornerRadius="1"
Background="#666666"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Button>
</Border>
</StackPanel>
</StackPanel>
</Border>
<Border Width="115" Height="210" Background="#f9f9f9" Margin="-40,0,0,0" CornerRadius="5" Padding="10">
<StackPanel Spacing="10">
<!--Resend Configration Btn-->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5" VerticalAlignment="Top" >
<Button Width="99" Height="33" Padding="5" Content="RE-SEND"
FontSize="18" HorizontalContentAlignment="Center"
Foreground="White" Background="#008000" Click="ResendConfig">
</Button>
</Border>
<!--PID Setting Btn-->
<Border Width="99" Height="33" Background="#E6E6E6" CornerRadius="5" VerticalAlignment="Top" >
<Button Width="99" Height="33" Padding="0,5" Content="SETTINGS"
FontSize="18" HorizontalContentAlignment="Center"
Foreground="White" Background="#ff5555"
Click="showPidPopUp"
>
</Button>
</Border>
</StackPanel>
</Border>
</StackPanel>
<Border
Grid.Row="2"
Width="195"
Height="124"
Background="#f9f9f9"
CornerRadius="5"
Margin="40,0,0,5" Padding="3,3,0,0">
<StackPanel Orientation="Vertical" Spacing="2">
<StackPanel Orientation="Horizontal" Spacing="3">
<Border
Width="28"
Height="28"
Background="#e6e6e6"
PointerPressed="ChangeTempMode"
Tag="t1"
>
<Button VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="#4d4d4d"
Background="Transparent"
Padding="0"
Click="ChangeTempMode"
Tag="t1"
>
M
</Button>
</Border>
<Border Width="158"
Height="28"
Background="#e6e6e6"
Padding="10,2,7,0"
Tag="t1"
PointerPressed="ShowNumberKeyBoard">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" x:Name="t1Container">
<TextBlock Grid.Column="0" FontSize="20" Foreground="#808080" >T-1 =</TextBlock>
<TextBlock x:Name="t1Text" Grid.Column="1" FontSize="20" Foreground="#808080">+0.0</TextBlock>
<TextBlock Grid.Column="2" FontSize="20" Foreground="#808080">°C</TextBlock>
</Grid>
</Grid>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="3">
<Border
Width="28"
Height="28"
Background="#e6e6e6"
PointerPressed="ChangeTempMode"
Tag="t2">
<Button VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="#4d4d4d"
Background="Transparent"
Padding="0"
Click="ChangeTempMode"
Tag="t2">
M
</Button>
</Border>
<Border Width="158"
Height="28"
Background="#e6e6e6"
Padding="10,2,7,0"
Tag="t2"
PointerPressed="ShowNumberKeyBoard">
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto"
x:Name="t2Container">
<TextBlock Grid.Column="0" FontSize="20" Foreground="#808080">T-2 =</TextBlock>
<TextBlock Grid.Column="1" FontSize="20" Foreground="#808080" x:Name="t2Text" >+0.0</TextBlock>
<TextBlock Grid.Column="2" FontSize="20" Foreground="#808080">°C</TextBlock>
</Grid>
</Grid>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="3">
<Border
Width="28"
Height="28"
Background="#e6e6e6"
PointerPressed="ChangeTempMode"
Tag="t3">
<Button VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="#4d4d4d"
Background="Transparent"
Padding="0"
Click="ChangeTempMode"
Tag="t3">
M
</Button>
</Border>
<Border Width="158"
Height="28"
Background="#e6e6e6"
Padding="10,2,7,0"
Tag="t3"
PointerPressed="ShowNumberKeyBoard">
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto"
x:Name="t3Container">
<TextBlock Grid.Column="0" FontSize="20" Foreground="#808080">T-3 =</TextBlock>
<TextBlock Grid.Column="1" FontSize="20" Foreground="#808080" x:Name="t3Text">+0.0</TextBlock>
<TextBlock Grid.Column="2" FontSize="20" Foreground="#808080">°C</TextBlock>
</Grid>
</Grid>
</Border>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="3">
<Border
Width="28"
Height="28"
Background="#e6e6e6"
PointerPressed="ChangeTempMode"
Tag="t4">
<Button VerticalAlignment="Center"
HorizontalAlignment="Center"
FontSize="18"
FontWeight="Bold"
Foreground="#4d4d4d"
Background="Transparent"
Padding="0"
Click="ChangeTempMode"
Tag="t4">
M
</Button>
</Border>
<Border Width="158"
Height="28"
Background="#e6e6e6"
Padding="10,2,7,0"
Tag="t4"
PointerPressed="ShowNumberKeyBoard">
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto"
x:Name="t4Container">
<TextBlock Grid.Column="0" FontSize="20" Foreground="#808080">T-4 =</TextBlock>
<TextBlock Grid.Column="1" FontSize="20" Foreground="#808080" x:Name="t4Text">+0.0</TextBlock>
<TextBlock Grid.Column="2" FontSize="20" Foreground="#808080">°C</TextBlock>
</Grid>
</Grid>
</Border>
</StackPanel>
</StackPanel>
</Border>
</Grid>
<!--Middel col-->
<Grid Grid.Column="1" RowDefinitions="Auto,Auto,Auto" Margin="0,0,0,0">
<!--first row in middel col-->
<Grid Grid.Row="0" ColumnDefinitions="*,1.07*">
<Grid Grid.Column="0" ColumnDefinitions="*,1.1*">
<Grid Grid.Column="0" >
<Grid Height="50" Width="14" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,0,0,10">
<Grid.Background>
<ImageBrush Source="/Assets/UpArrow.png"/>
</Grid.Background>
</Grid>
</Grid>
<Grid Grid.Column="1">
<StackPanel Orientation="Horizontal" Spacing="5">
<!--Motore 1-->
<Border CornerRadius="10" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="116" Height="73" Margin="3,0,0,0" Background="#F9F9F9" Padding="0">
<StackPanel Spacing="2">
<!-- First row: ACTIVE -->
<Border
CornerRadius="4"
Padding="0"
>
<Button Width="110" Height="32" Padding="0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid ColumnDefinitions="*,Auto"
VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Foreground="#231F20" Text="Curr="
FontSize="18"
/>
<TextBlock x:Name="curr1" Foreground="#AF196F" Text="0.0"
FontSize="18"/>
<TextBlock Foreground="#231F20" Text="A"
FontSize="18"/>
</StackPanel>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border
CornerRadius="4"
Padding="0"
>
<Button Width="110" Height="32" Padding="0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6" Click="motorClick">
<Grid ColumnDefinitions="*,Auto"
VerticalAlignment="Center" Classes="motorState" Tag="0">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-10,0,0" >
<TextBlock Foreground="#231F20" Text="MOT-1 "
FontSize="18"/>
<TextBlock Foreground="#231F20" Text="OFF"
FontSize="18"/>
</StackPanel>
<Border CornerRadius="5" Margin="0,0,0,-8"
Width="104" Height="5"
Background="#666666"
HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>
</Button>
</Border>
</StackPanel>
</Border>
<!--Motore 2-->
<Border CornerRadius="10" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="116" Height="73" Margin="3,0,0,0" Background="#F9F9F9">
<StackPanel Spacing="2">
<!-- First row -->
<Border
CornerRadius="4"
Padding="0"
>
<Button Width="110" Height="32" Padding="0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid ColumnDefinitions="*,Auto"
VerticalAlignment="Center">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Foreground="#231F20" Text="Curr="
FontSize="18"/>
<TextBlock x:Name="curr2" Foreground="#AF196F" Text="0.0"
FontSize="18"/>
<TextBlock Foreground="#231F20" Text="A"
FontSize="18"/>
</StackPanel>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border
CornerRadius="4"
Padding="0"
>
<Button Width="110" Height="32" Padding="0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6" Click="motorClick">
<Grid ColumnDefinitions="*,Auto"
VerticalAlignment="Center" Classes="motorState" Tag="1">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-10,0,0">
<TextBlock Foreground="#231F20" Text="MOT-2 "
FontSize="18"/>
<TextBlock Foreground="#231F20" Text="OFF"
FontSize="18"/>
</StackPanel>
<Border CornerRadius="5" Margin="0,0,0,-8"
Width="104" Height="5"
Background="#666666"
HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
</Grid>
</Button>
</Border>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Column="1" >
<StackPanel Orientation="Horizontal">
<Grid Height="50" Width="14" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="0,0,10,10">
<Grid.Background>
<ImageBrush Source="/Assets/UpArrow.png"/>
</Grid.Background>
</Grid>
<Border Width="340" Height="82" Background="#F9F9F9" HorizontalAlignment="Left" CornerRadius="5" VerticalAlignment="Bottom" Padding="3,5,0,0">
<StackPanel Orientation="Vertical">
<!-- Top label -->
<TextBlock Text="HIGH VOLT OUTPUTS"
Foreground="#A4A2A3"
FontSize="17"
TextWrapping="Wrap"
HorizontalAlignment="Center"
/>
<StackPanel Orientation="Horizontal" Spacing="9">
<!-- First row: ACTIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="hvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="hvo" Tag="0">
<TextBlock Grid.Row="0" FontSize="19" Text="1" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="hvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="hvo" Tag="1">
<TextBlock Grid.Row="0" FontSize="19" Text="2" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- Third row: PASSIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="hvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="hvo" Tag="2">
<TextBlock Grid.Row="0" FontSize="19" Text="3" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- Fourth row: PASSIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="hvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="hvo" Tag="3">
<TextBlock Grid.Row="0" FontSize="19" Text="4" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<StackPanel Orientation="Horizontal" Margin="25,0,0,0" Spacing="33">
<!-- Fifth row: ACTIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="hvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="hvo" Tag="4">
<TextBlock Grid.Row="0" FontSize="19" Text="5" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- Sixth row: ACTIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="hvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="hvo" Tag="5">
<TextBlock Grid.Row="0" FontSize="19" Text="6" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</Grid>
<!--second row in middel col-->
<Grid Grid.Row="1" Width="974" Height="392" ColumnDefinitions="*,10*">
<Grid Grid.Column="0" RowDefinitions="0.21*,1.31*">
<Grid Grid.Row="0"></Grid>
<StackPanel Grid.Row="1" Spacing="30.8" Height="215" Orientation="Vertical" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,5,0">
<Ellipse Classes="in" Tag="0" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="in" Tag="1" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="in" Tag="2" Width="10" Height="10" Fill="#666666" Margin="0,0,0,0"/>
<Ellipse Classes="in" Tag="3" Width="10" Height="10" Fill="#666666" Margin="0,0,0,0"/>
<Ellipse Classes="in" Tag="4" Width="10" Height="10" Fill="#666666" Margin="0,0,0,0"/>
<Ellipse Classes="in" Tag="5" Width="10" Height="10" Fill="#666666"/>
</StackPanel>
</Grid>
<Grid Grid.Column="1" ColumnDefinitions="*,6*">
<Grid Grid.Column="0" Width="73" Height="40" Margin="35,-30,0,0" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Orientation="Vertical" VerticalAlignment="Top">
<TextBlock FontSize="18" Foreground="White">T-Board</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="internalTemp" FontSize="18" Foreground="White" Margin="6,0,0,0">0</TextBlock>
<TextBlock FontSize="18" Foreground="White" >°C</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
<Grid Grid.Column="1" RowDefinitions="*,2.1*,*">
<Grid Grid.Row="0" ></Grid>
<Grid Grid.Row="1" RowDefinitions="*,*">
<Grid Grid.Row="0" ColumnDefinitions="*,*,*" >
<Grid Grid.Column="0" Width="130" Margin="20,0,0,15">
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Spacing="115">
<Ellipse Classes="motorState" Tag="0" Width="10" Height="10" Fill="#666666" />
<Ellipse Classes="motorState" Tag="1" Width="10" Height="10" Fill="#666666"/>
</StackPanel>
</Grid>
<Grid Grid.Column="1" Width="155" Margin="-10,0,0,15" >
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Spacing="40">
<Ellipse Classes="hvo" Tag="0" Width="10" Height="10" Fill="#666666" />
<Ellipse Classes="hvo" Tag="1" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="hvo" Tag="2" Width="10" Height="10" Fill="#666666" Margin="-2,0,0,0"/>
<Ellipse Classes="hvo" Tag="3" Width="10" Height="10" Fill="#666666" Margin="0,0,0,0"/>
</StackPanel>
</Grid>
<Grid Grid.Column="2" Width="" Margin="14,0,0,15" Background="" >
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Spacing="65">
<Ellipse Classes="hvo" Tag="4" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="hvo" Tag="5" Width="10" Height="10" Fill="#666666"/>
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Row="1" ColumnDefinitions="*,2*">
<Grid Grid.Column="0" Background="">
<StackPanel Orientation="Vertical" VerticalAlignment="Bottom" Margin="20,0,0,0">
<TextBlock FontSize="18" Foreground="White">T-Cooler</TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="hsTemp" FontSize="18" Foreground="White" Margin="6,0,0,0">0</TextBlock>
<TextBlock FontSize="18" Foreground="White" >°C</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
<Grid Grid.Column="1" Background="">
<StackPanel Orientation="Horizontal" Margin="18,0,0,0" VerticalAlignment="Bottom" Spacing="40">
<Ellipse Classes="lvo" Tag="0" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="lvo" Tag="1" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="lvo" Tag="2" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="lvo" Tag="3" Width="10" Height="10" Fill="#666666" Margin="-1,0,0,0"/>
<StackPanel Margin="0,0,0,15" Orientation="Vertical" Spacing="5">
<Ellipse Classes="lvo" Tag="5" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="lvo" Tag="4" Width="10" Height="10" Fill="#666666"/>
</StackPanel>
<StackPanel Margin="0,0,0,15" Orientation="Vertical" Spacing="5">
<Ellipse Classes="lvo" Tag="7" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="lvo" Tag="6" Width="10" Height="10" Fill="#666666"/>
</StackPanel>
<StackPanel Margin="0,0,0,15" Orientation="Vertical" Spacing="5">
<Ellipse Classes="lvo" Tag="9" Width="10" Height="10" Fill="#666666"/>
<Ellipse Classes="lvo" Tag="8" Width="10" Height="10" Fill="#666666"/>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
</Grid>
<Grid Grid.Row="2" ColumnDefinitions="*,*,1.1*" Background="">
<Grid Background="" Grid.Column="2">
<Ellipse x:Name="extPowerLed" Classes="VDC" Margin="0,0,0,30" Width="10" Height="10" Fill="#666666"/>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid.Background >
<ImageBrush Source="/Assets/Board.png"/>
</Grid.Background>
</Grid>
<!--third row in middel col-->
<Grid Grid.Row="2" ColumnDefinitions="0.3*,2*,1.9*,0.1*" Margin="0,3,0,5">
<Grid Grid.Column="0" ></Grid>
<Grid Grid.Column="1" ColumnDefinitions="*,*" >
<Grid Grid.Column="0" Height="50" Width="14" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5,0,-40,0">
<Grid.Background>
<ImageBrush Source="/Assets/RedUpArrow.png"/>
</Grid.Background>
</Grid>
<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top"
HorizontalAlignment="Right" Margin="0,0,0,0" Spacing="5">
<StackPanel >
<!--ANA 1-->
<Border CornerRadius="10" VerticalAlignment="Top" HorizontalAlignment="Right" Width="146" Height="93" Margin="3,0,0,8" Background="#F9F9F9" Padding="5">
<StackPanel Spacing="2">
<!-- First row: ACTIVE -->
<Border
CornerRadius="4"
Padding="0"
>
<Button Width="140" Height="28" Padding="0" Margin="0" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="AN-1 ="
FontSize="20" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<TextBlock x:Name="an1" Grid.Column="1" Text="0.0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="%" FontSize="20" HorizontalAlignment="Center"/>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border
CornerRadius="4"
Padding=""
>
<Button Width="140" Height="28" Padding="0" Margin="0" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="AN-2 ="
FontSize="20" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<TextBlock x:Name="an2" Grid.Column="1" Text="0.0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="%" FontSize="20" HorizontalAlignment="Center"/>
</Grid>
</Button>
</Border>
<!-- Top label -->
<TextBlock Text="ANALOG INPUTS"
Foreground="#918F90"
FontSize="16"
Margin="0,3,0,0"
HorizontalAlignment="Center"
/>
</StackPanel>
</Border>
<TextBlock FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center" >Temps Control</TextBlock>
<Grid Grid.Column="0" Height="10" Width="191" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,0">
<Grid.Background>
<ImageBrush Source="/Assets/TempArrow.png"/>
</Grid.Background>
</Grid>
</StackPanel>
<!--T-1,2,3,4-->
<Border CornerRadius="10" VerticalAlignment="Top" HorizontalAlignment="Left" Width="164" Height="124" Margin="3,0,0,0" Background="#F9F9F9" Padding="2">
<StackPanel Spacing="-2">
<!-- First row: ACTIVE -->
<Border
CornerRadius="4"
Padding=""
>
<Button Width="158" Height="28" Padding="5,0,2,0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid RowDefinitions="Auto">
<Grid Grid.Row="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Foreground="#231F20" Text="T-1 =" FontSize="20" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<TextBlock x:Name="t1" Text="0.0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center"/>
</StackPanel>
<TextBlock Grid.Column="1" Foreground="#231F20" Text="°C" FontSize="20" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border
CornerRadius="4"
Padding=""
>
<Button Width="158" Height="28" Padding="5,0,2,0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid RowDefinitions="Auto">
<Grid Grid.Row="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Foreground="#231F20" Text="T-2 =" FontSize="20" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<TextBlock x:Name="t2" Text="0.0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center"/>
</StackPanel>
<TextBlock Grid.Column="1" Foreground="#231F20" Text="°C" FontSize="20" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- third row: PASSIVE -->
<Border
CornerRadius="4"
Padding=""
>
<Button Width="158" Height="28" Padding="5,0,2,0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid RowDefinitions="Auto">
<Grid Grid.Row="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Foreground="#231F20" Text="T-3 =" FontSize="20" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<TextBlock x:Name="t3" Text="0.0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center"/>
</StackPanel>
<TextBlock Grid.Column="1" Foreground="#231F20" Text="°C" FontSize="20" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Button>
</Border>
<!-- fourth row: PASSIVE -->
<Border
CornerRadius="4"
Padding=""
>
<Button Width="158" Height="28" Padding="5,0,2,0" Margin="2" HorizontalAlignment="Center" Background="#E6E6E6">
<Grid RowDefinitions="Auto">
<Grid Grid.Row="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<TextBlock Foreground="#231F20" Text="T-4 =" FontSize="20" HorizontalAlignment="Center" Margin="5,0,0,0"/>
<TextBlock x:Name="t4" Text="0.0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center"/>
</StackPanel>
<TextBlock Grid.Column="1" Foreground="#231F20" Text="°C" FontSize="20" HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Button>
</Border>
</StackPanel>
</Border>
<Grid Height="50" Width="14" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,0,5,0">
</Grid>
</StackPanel>
</Grid>
<Grid Grid.Column="2" RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,*">
<Grid Grid.Column="0">
<Border Grid.Column="0" Width="343" Height="95" Background="#F9F9F9" HorizontalAlignment="Left" CornerRadius="5" VerticalAlignment="Top" Padding="2"
Margin="0,0,5,0">
<Grid RowDefinitions="*" >
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto">
<StackPanel Grid.Column="0" Margin="0,0,8,0">
<StackPanel Orientation="Horizontal" Spacing="10" >
<!-- First row: ACTIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="lvo" Tag="0">
<TextBlock Grid.Row="0" FontSize="19" Text="1" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- Second row: PASSIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="lvo" Tag="1">
<TextBlock Grid.Row="0" FontSize="19" Text="2" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- third row: PASSIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="lvo" Tag="2">
<TextBlock Grid.Row="0" FontSize="19" Text="3" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
<!-- Fourth row: PASSIVE -->
<Border
CornerRadius="4" >
<Button Width="40" Height="54" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<Grid RowDefinitions="*,Auto,Auto"
VerticalAlignment="Center" HorizontalAlignment="Center" Classes="lvo" Tag="3">
<TextBlock Grid.Row="0" FontSize="19" Text="4" Foreground="#231F20"
VerticalAlignment="Top" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" FontSize="19" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,0,0"/>
<!-- Colored bar on the right -->
<Border Grid.Row="2"
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</Grid>
</Button>
</Border>
</StackPanel>
<!-- Bottom label -->
<TextBlock Text="LOW VOLT OUTPUTS"
Foreground="#A4A2A3"
FontSize="17"
TextWrapping="Wrap"
HorizontalAlignment="Left"
Margin="6,6,0,0"
/>
</StackPanel>
<StackPanel Orientation="Horizontal" Grid.Column="1" Spacing="9">
<!-- Fifth row: ACTIVE -->
<StackPanel Spacing="3">
<Border
CornerRadius="4" >
<Button Width="40" Height="44" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<StackPanel Orientation="Vertical" Spacing="-3" Classes="lvo" Tag="5">
<TextBlock FontSize="19" Text="6" Foreground="#231F20"
HorizontalAlignment="Center"/>
<TextBlock FontSize="15.7" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-3,0,0"/>
<!-- Colored bar on the right -->
<Border
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</StackPanel>
</Button>
</Border>
<Border
CornerRadius="4" >
<Button Width="40" Height="44" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<StackPanel Orientation="Vertical" Spacing="-3" Classes="lvo" Tag="4">
<TextBlock FontSize="19" Text="5" Foreground="#231F20"
HorizontalAlignment="Center"/>
<TextBlock FontSize="15.7" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-3,0,0"/>
<!-- Colored bar on the right -->
<Border
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</StackPanel>
</Button>
</Border>
</StackPanel>
<!-- Sixth row: ACTIVE -->
<StackPanel Spacing="3" >
<Border
CornerRadius="4" >
<Button Width="40" Height="44" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<StackPanel Orientation="Vertical" Spacing="-3" Classes="lvo" Tag="7">
<TextBlock FontSize="19" Text="8" Foreground="#231F20"
HorizontalAlignment="Center"/>
<TextBlock FontSize="15.7" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-3,0,0"/>
<!-- Colored bar on the right -->
<Border
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</StackPanel>
</Button>
</Border>
<Border
CornerRadius="4" >
<Button Width="40" Height="44" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<StackPanel Orientation="Vertical" Spacing="-3" Classes="lvo" Tag="6">
<TextBlock FontSize="19" Text="7" Foreground="#231F20"
HorizontalAlignment="Center"/>
<TextBlock FontSize="15.7" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-3,0,0"/>
<!-- Colored bar on the right -->
<Border
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</StackPanel>
</Button>
</Border>
</StackPanel>
<!-- Seventh row: ACTIVE -->
<StackPanel Spacing="3" >
<Border
CornerRadius="4" >
<Button Width="40" Height="44" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<StackPanel Orientation="Vertical" Spacing="-3" Classes="lvo" Tag="9">
<TextBlock FontSize="19" Text="10" Foreground="#231F20"
HorizontalAlignment="Center"/>
<TextBlock FontSize="15.7" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-3,0,0"/>
<!-- Colored bar on the right -->
<Border
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</StackPanel>
</Button>
</Border>
<Border
CornerRadius="4" >
<Button Width="40" Height="44" Padding="0" HorizontalAlignment="Center" Background="#E6E6E6" Click="lvoClick">
<StackPanel Orientation="Vertical" Spacing="-3" Classes="lvo" Tag="8">
<TextBlock FontSize="19" Text="9" Foreground="#231F20"
HorizontalAlignment="Center"/>
<TextBlock FontSize="15.7" Text="OFF" Foreground="#231F20"
VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,-3,0,0"/>
<!-- Colored bar on the right -->
<Border
Width="32" Height="5"
Background="#666666"
HorizontalAlignment="Center"
VerticalAlignment="Bottom" CornerRadius="5" Margin="0,0,0,0"/>
</StackPanel>
</Button>
</Border>
</StackPanel>
</StackPanel>
</Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal" Spacing="7">
</StackPanel>
</StackPanel>
</Grid>
</Border>
</Grid>
<Grid Grid.Column="1" Margin="0,0,0,0">
<Border Grid.Column="1" Width="91" Height="82" Background="#F9F9F9" VerticalAlignment="Top"
CornerRadius="5" Padding="4,0"
Margin="0,0,0,0">
<StackPanel Orientation="Vertical" Spacing="0">
<StackPanel Orientation="Horizontal" Spacing="5" Margin="0,0,0,0">
<TextBlock x:Name="ExtPwr" Text="0" FontSize="20" Foreground="#AF196F" HorizontalAlignment="Center" Margin="3,0,0,0"/>
<TextBlock Foreground="#231F20" Text="VDC" FontSize="20" HorizontalAlignment="Center" Margin="0,0,0,0"/>
</StackPanel>
<!-- Bottom text -->
<StackPanel Orientation="Vertical" Spacing="-5">
<TextBlock Text="EXTERNAL"
Foreground="#918f90"
FontSize="16"
TextWrapping="Wrap"
HorizontalAlignment="Center"
/>
<TextBlock Text="POWER"
Foreground="#918f90"
FontSize="16"
TextWrapping="Wrap"
HorizontalAlignment="Center"
/>
<TextBlock Text="VOLTAGE"
Foreground="#918f90"
FontSize="16"
TextWrapping="Wrap"
HorizontalAlignment="Center"
/>
</StackPanel>
</StackPanel>
</Border>
</Grid>
<Grid Grid.Column="2" Margin="0,0,25,0">
<Grid Grid.Column="2" Height="50" Width="14" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5,0,0,0">
<Grid.Background>
<ImageBrush Source="/Assets/RedUpArrow.png"/>
</Grid.Background>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid Grid.Column="3" >
</Grid>
</Grid>
</Grid>
<!--right col-->
<Grid Grid.Column="2"
RowDefinitions="0.9*,3*,*">
<Grid Grid.Row="0" ></Grid>
<Grid Grid.Row="1" >
<StackPanel Orientation="Vertical" VerticalAlignment="Top" Spacing="5">
<!-- Right arrow -->
<Grid Height="14" Width="50" Margin="0,0,0,0">
<Grid.Background>
<ImageBrush Source="/Assets/LeftArrow.png"/>
</Grid.Background>
</Grid>
<!--Power Input-->
<Border CornerRadius="5" VerticalAlignment="Top" Width="147" Height="125" Margin="3,0,0,0" Padding="0" Background="#F9F9F9">
<StackPanel>
<!-- Top label -->
<TextBlock Text="POWER INPUT"
Foreground="#A4A2A3"
FontSize="17"
TextWrapping="Wrap"
HorizontalAlignment="Center"
/>
<StackPanel Spacing="5">
<!-- First row: ACTIVE -->
<Border
Width="141" Height="52"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
>
<Button Width="141" Height="52" Padding="0,0,5,0" Margin="0" HorizontalAlignment="Center" Background="Transparent">
<Grid RowDefinitions="*,*,*">
<Grid Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="VAC Ph1: " FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBlock x:Name="ph1" Grid.Column="1" Text="0" FontSize="16.5" Foreground="#AF196F" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="V" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
<Grid Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="VAC Ph2:" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBlock x:Name="ph2" Grid.Column="1" Text="0" FontSize="16.5" Foreground="#AF196F" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="V" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
<Grid Grid.Row="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="VAC Ph3:" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBlock x:Name="ph3" Grid.Column="1" Text="0" FontSize="16.5" Foreground="#AF196F" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="V" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
</Grid>
</Button>
</Border>
<!-- Second row: ACTIVE -->
<Border
Width="141" Height="20"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
>
<StackPanel Orientation="Vertical" Spacing="-8">
<Button Width="141" Height="20" Padding="0,0,5,0" Margin="" HorizontalAlignment="Center" Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="I-Neutral:" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBlock x:Name="i_nut" Grid.Column="1" Text="0.0" FontSize="16.5" Foreground="#AF196F" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="A" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Button>
</StackPanel>
</Border>
<!-- third row: ACTIVE -->
<Border
Width="141" Height="20"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
>
<StackPanel Orientation="Vertical" Spacing="-8">
<Button Width="141" Height="20" Padding="0,0,3,0" Margin="" HorizontalAlignment="Center" Background="Transparent">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Foreground="#231F20" Text="Grid Freq:" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0"/>
<TextBlock x:Name="gridFreq" Grid.Column="1" Text="0.0" FontSize="16.5" Foreground="#AF196F" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Grid.Column="2" Foreground="#231F20" Text="Hz" FontSize="16.5" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Button>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</Border>
<!--Error Falgs-->
<Border CornerRadius="5" VerticalAlignment="Top" Width="148" Height="211" BorderBrush="#FE3636" BorderThickness="1" Margin="3,0,0,0" Padding="3,5,3,1" Background="#F9F9F9">
<Grid ColumnDefinitions="*">
<Grid Grid.Column="0" RowDefinitions="*,Auto">
<Grid Grid.Row="0">
<StackPanel Orientation="Vertical" >
<!-- Top label -->
<TextBlock Text="BOARD FLAGS"
FontSize="17"
Foreground="#FE3636"
HorizontalAlignment="Center"
/>
<StackPanel Spacing="2" Orientation="Vertical">
<!-- First row: ACTIVE -->
<Border
Width="141" Height="36"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
>
<StackPanel Orientation="Vertical" Spacing="-8">
<Button Width="141" Height="36" Padding="0" Margin="0" HorizontalAlignment="Center" Background="Transparent">
<Grid RowDefinitions="*,*">
<Grid Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="ComPort1" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle
Classes="flag" Tag="1"
Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
<Grid Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="ComPort2" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="2" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
</Grid>
</Button>
</StackPanel>
</Border>
<!-- Second row: ACTIVE -->
<Border
Width="141" Height="20"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
>
<StackPanel Orientation="Vertical" Spacing="-8">
<Button Width="141" Height="20" Padding="0" Margin="0" HorizontalAlignment="Center" Background="Transparent">
<Grid RowDefinitions="*">
<Grid Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="NoExtPower" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="3" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
</Grid>
</Button>
</StackPanel>
</Border>
<!-- third row: ACTIVE -->
<Border
Width="141" Height="36"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
x:Name="phaseContainer">
<StackPanel Orientation="Vertical" Spacing="-8">
<Button Width="141" Height="36" Padding="0" Margin="0" HorizontalAlignment="Center" Background="Transparent">
<Grid RowDefinitions="*,*">
<Grid Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="PhaseSequ" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="4" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
<Grid Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="PhaseLack" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="5" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
</Grid>
</Button>
</StackPanel>
</Border>
<!-- forth row: ACTIVE -->
<Border
Width="141" Height="52"
CornerRadius="4"
Background="#E6E6E6"
Padding="5,0,0,0"
>
<StackPanel Orientation="Vertical" Spacing="-8">
<Button Width="141" Height="52" Padding="0" Margin="0" HorizontalAlignment="Center" Background="Transparent">
<Grid RowDefinitions="*,*,*">
<Grid Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="HiCurrNeut" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="6" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
<Grid Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="HiCurrMot1" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="7" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
<Grid Grid.Row="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="HiCurrMot2" Foreground="#020202"
VerticalAlignment="Center" FontSize="17"/>
<Rectangle Classes="flag" Tag="8" Grid.Column="1" RadiusX="4" RadiusY="4" Width="12" Height="12" Fill="#666666" HorizontalAlignment="Right" Margin="0,0,5,0" ></Rectangle>
</Grid>
</Grid>
</Grid>
</Button>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</Grid>
<Grid Grid.Row="1" >
<!--Rest Button-->
<Button Width="141" Height="20" Content="RESET ERRORS" Background="#FF5555" Padding="0,0,0,0"
VerticalAlignment="Center"
FontSize="16"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Foreground="#FFFFFF" Click="resetErrorClick">
<Button.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="#FFFFFF"></Setter>
<Setter Property="Background" Value="#FF0000"></Setter>
</Style>
</Button.Styles>
<TextBlock FontSize="16" >RESET ERRORS</TextBlock>
</Button>
</Grid>
</Grid>
</Grid>
</Border>
</StackPanel>
</Grid>
<Grid Grid.Row="2" >
<Border
Background="#f9f9f9"
CornerRadius="5"
Width="148"
Height="51"
BorderBrush="#008000"
BorderThickness="1.5"
Padding="5"
VerticalAlignment="Top"
Margin="3,0,0,0">
<StackPanel>
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="#ff0000"
FontSize="16"
FontWeight="Medium">CALIP. Not Done</TextBlock>
<Button
Width="141"
Height="20"
Background="#008000"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Foreground="#ffffff"
FontSize="15.5"
Padding="0"
Content="CALIPRATE">
</Button>
</StackPanel>
</Border>
</Grid>
</Grid>
</Grid>
<!-- Overlay Background for Calibration Popup -->
<Border x:Name="calibrationPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="10" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="5">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="Calibration Done/Not Done"
FontSize="20"
FontWeight="Bold"
Foreground="#ff0000"
HorizontalAlignment="Center"
Margin="0,0,0,8" />
<Grid RowDefinitions="*" Background="Red">
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto">
<!--col 1-->
<Grid Grid.Column="0" Background="Yellow" RowDefinitions="*,*" Margin="5" >
<Grid Grid.Row="0" >
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock VerticalAlignment="Center"
FontSize="20"
Foreground="#ff0000" Margin="0,0,5,0">Temp Max:</TextBlock>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
1
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
2
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
3
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
4
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
ALL
</Button>
</StackPanel>
</Grid>
<Grid Grid.Row="1" >
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock VerticalAlignment="Center"
FontSize="20"
Foreground="#0000aa" Margin="0,0,12,0">Temp Min:</TextBlock>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
1
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
2
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
3
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
4
</Button>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
FontSize="20"
Padding="0">
ALL
</Button>
</StackPanel>
</Grid>
</Grid>
<!--col 2-->
<Grid Grid.Column="1" >
<StackPanel HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="130">
<TextBlock
FontSize="20" Margin="0,0,11,0"
HorizontalAlignment="Center">Currents</TextBlock>
<TextBlock
FontSize="20"
Margin="0,0,11,0"
HorizontalAlignment="Center"
>Calibration:</TextBlock>
<Button Width="50"
Height="50"
Background="#E6E6E6"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
HorizontalAlignment="Center"
FontSize="20"
Padding="0"
Margin="0,0,10,0">
1
</Button>
</StackPanel>
</Grid>
</Grid>
</Grid>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<!-- Close Button -->
<Button
Content="Close"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="">
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!--number keyBoard-->
<Border x:Name="keyBoardPopup"
Background="#80000000"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="False"
ZIndex="50"
PointerPressed="OnPopupOverlayPointerPressed">
<Grid MaxWidth="500" MaxHeight="500" HorizontalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,0,0"
PointerPressed="InnerPopupPointerPressed">
<Border x:Name="PopupControl"
BorderThickness="2"
CornerRadius="10"
Padding="10"
PointerPressed="InnerPopupPointerPressed">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="10">
<!-- Popup Content (Keypad etc.) -->
<Grid IsVisible="True">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="FontSize" Value="50"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="RenderTransform" Value="scale(1.11)"/>
</Style>
</Grid.Styles>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!-- Keypad Buttons -->
<Button Content="1" Grid.Row="0" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="2" Grid.Row="0" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="3" Grid.Row="0" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="4" Grid.Row="1" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="5" Grid.Row="1" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="6" Grid.Row="1" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="7" Grid.Row="2" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="8" Grid.Row="2" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="9" Grid.Row="2" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="BACK" Grid.Row="3" Grid.Column="0" FontSize="20" Background="#D3D3D3" Margin="5" Click="OnBackClick"/>
<Button Content="0" Grid.Row="3" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button x:Name="enterBtn" Content="ENTER" Grid.Row="3" Grid.Column="2" FontSize="20" Background="#A4275D" Foreground="White" Margin="5" Click="EnterClick"/>
<Button Content="-" Grid.Row="3" Grid.Column="3" FontSize="50" Background="White" Foreground="Black"
Margin="5" Click="OnKeyClick"/>
<Button Content="+" Grid.Row="2" Grid.Column="3" FontSize="50" Background="White" Foreground="Black"
Margin="5" Click="OnKeyClick"/>
<Button Content="." Grid.Row="1" Grid.Column="3" FontSize="50" Background="White" Foreground="Black"
Margin="5" Click="OnKeyClick"/>
</Grid>
</Grid>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="innerPidPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnIgnoreInnerPidPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="header" Tag="0" Text="PID T-1 FACTORS"
FontSize="20"
FontWeight="Bold"
Foreground="#A4275D"
Margin="0,0,0,8" />
<StackPanel Spacing="5" Margin="0,0,0,30">
<!-- Add button styles at the top of the StackPanel -->
<StackPanel.Styles>
<Style Selector="Button.circleButton">
<Setter Property="Width" Value="32"/>
<Setter Property="Height" Value="32"/>
<Setter Property="Background" Value="#E6E6E6"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="CornerRadius" Value="16"/>
<Setter Property="Foreground" Value="#af196f"/>
<Setter Property="FontSize" Value="25"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center">
<TextBlock Text="{TemplateBinding Content}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="{TemplateBinding FontSize}"
Foreground="{TemplateBinding Foreground}"
FontWeight="{TemplateBinding FontWeight}"
TextAlignment="Center"
Margin="0,0,0,2"/>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
</StackPanel.Styles>
<!-- KP Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KP: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="kpSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KpMinusClick"
x:Name="kpMinusBtn"/>
<Slider Grid.Column="1"
x:Name="kpSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KpSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KpPlusClick"
x:Name="kpPlusBtn"/>
</Grid>
<!-- KI Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KI: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="kiSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KiMinusClick"
x:Name="kiMinusBtn"/>
<Slider Grid.Column="1"
x:Name="kiSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KiSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KiPlusClick"
x:Name="kiPlusBtn"/>
</Grid>
<!-- KD Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KD: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="kdSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KdMinusClick"
x:Name="kdMinusBtn"/>
<Slider Grid.Column="1"
x:Name="kdSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KdSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KdPlusClick"
x:Name="kdPlusBtn"/>
</Grid>
<!-- KL Control -->
<StackPanel Orientation="Horizontal">
<TextBlock Text="KL: "
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"/>
<TextBlock FontSize="16"
FontWeight="Bold"
x:Name="klSliderValue"
Margin="0,0,0,0"
Foreground="Black"
MinWidth="30"
TextAlignment="Left">0</TextBlock>
</StackPanel>
<Grid ColumnDefinitions="Auto,*,Auto" Margin="5,0">
<Button Grid.Column="0"
Content=""
Classes="circleButton"
Click="KlMinusClick"
x:Name="klMinusBtn"/>
<Slider Grid.Column="1"
x:Name="klSlider"
Minimum="0"
Maximum="100"
TickFrequency="1"
IsSnapToTickEnabled="True"
Margin="10,0"
ValueChanged="KlSliderValueChanged"/>
<Button Grid.Column="2"
Content="+"
Classes="circleButton"
Click="KlPlusClick"
x:Name="klPlusBtn"/>
</Grid>
<TextBlock Text="PID Activation Threshold (°C)"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"
/>
<Border Name="heatConRangeBorder" >
<TextBox Name="heatConRange"
KeyUp="OnKeyUp"></TextBox>
</Border>
<TextBlock Text="Fast Cooling Threshold (°C)"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="5,0"
/>
<Border Name="fcThresholdBorder" >
<TextBox Name="fcThreshold"
KeyUp="OnKeyUp"></TextBox>
</Border>
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10" Margin="0,-45,0,0">
<!-- yes Button -->
<Button
x:Name="okBtn"
Content="OK"
FontSize="16"
Padding="10,5"
Click="YesBtnClick"
Width="75"
Foreground="White"
HorizontalContentAlignment="Center">
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#A4275D"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
<!-- No Button -->
<Button
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Width="75"
Click="OnIgnoreInnerPidPopupOverlayPointerPressed">
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="pidPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnIgnorePidPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="pidHeader" Text="Choose PID FACTOR"
FontSize="20"
FontWeight="Bold"
Foreground="#A4275D"
HorizontalAlignment="Center"
Margin="0,0,0,8" />
<StackPanel Spacing="15">
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Content="T-1 SETTINGS"
Tag="1"
Click="showInnerPid">
</Button>
</Border>
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Tag="2"
Content="T-2 SETTINGS"
Click="showInnerPid">
</Button>
</Border>
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Tag="3"
Content="T-3 SETTINGS"
Click="showInnerPid">
</Button>
</Border>
<Border
Width="210"
Height="40"
Background="#e6e6e6"
CornerRadius="5" Padding="5">
<Button
Padding="0"
Grid.Column="0"
FontSize="22.5"
Foreground="#231f20"
HorizontalAlignment="Center"
Background="Transparent"
Tag="4"
Content="T-4 SETTINGS"
Click="showInnerPid">
</Button>
</Border>
</StackPanel>
<!-- Button Panel -->
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/Diagnostics.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using AvaloniaApplication1.DataBase;
using DaireApplication.DataBase;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Tracing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace DaireApplication;
public partial class Diagnostics : UserControl
{
private MainWindow? _mainWindow;
private ErrorSettingsTable _error=new();
public ConfigrationTable _configration;
private Process? _keyboardProcess;
public string GrayColor="#666666";
public string RedColor= "#FF0000";
public string GreenColor= "#71C837";
public string PinkColor= "#AF196F";
public string OrangeColor= "#FF6600";
public List<Rectangle> flagRectangles { get; set; }
public List<Control> InputesElements { get; set; }
public List<Control> MotoreState { get; set; }
public List<Control> hvoOutPuts { get; set; }
public List<Control> lvoOutPuts { get; set; }
TextBlock targetText = new TextBlock();
Button targetButton = new Button();
float oldValue = 0;
bool isNegative = false;
bool _isAdvSettings;
bool _isFromManualControl;
public MachineTable _machine { get; set; }
public Diagnostics()
{
InitializeComponent();
}
public Diagnostics(MainWindow mainWindow,bool isAdvSettings=false, bool isFromManualControl=false)
{
_mainWindow = mainWindow;
_machine = new MachineTable();
_configration = new();
_isAdvSettings = isAdvSettings;
_isFromManualControl = isFromManualControl;
InitializeComponent();
setDefaultSettings();
getUiElementes();
fcThreshold.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
heatConRange.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
fcThresholdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
heatConRangeBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
AttachHandlers(_mainWindow.logoBtn, AdvanceSettingsView);
}
public void AttachHandlers(Button button, System.EventHandler<Avalonia.Input.HoldingRoutedEventArgs> func)
{
if (button != null)
{
button.Holding += func;
button.PointerPressed += (sender, e) =>
{
// Simulate a long press on any pointer (mouse or touch)
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type));
};
button.PointerReleased += (sender, e) =>
{
// End simulated long press
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type));
};
}
}
public void AdvanceSettingsView(object? sender, RoutedEventArgs e)
{
if (_mainWindow.ContentArea.Content == this)
{
_mainWindow.ContentArea.Content = new AdvanceSettings(_mainWindow,true,false);
}
}
public void ResendConfig(object? sender, RoutedEventArgs e)
{
if (!_mainWindow.sendConfig)
{
_mainWindow.reSendHolding = true;
}
}
public static void CloseApplication(object? sender, RoutedEventArgs e)
{
var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
lifetime?.Shutdown(); // This should correctly shut down the application
}
private async void motorClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var grid= button.Content as Grid;
var stackPanel = grid.Children[0] as StackPanel;
var text = stackPanel.Children[1] as TextBlock;
if (text.Text=="ON")
{
_mainWindow.holdingRegister.motor = (ushort)(_mainWindow.holdingRegister.motor & ~(1 << int.Parse(grid.Tag.ToString())));
}
else if (text.Text == "OFF")
{
_mainWindow.holdingRegister.motor = (ushort)(_mainWindow.holdingRegister.motor | (1 << int.Parse(grid.Tag.ToString())));
}
await _mainWindow.WriteToSerialAsync("motorClick");
}
}
private async void hvoClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var grid= button.Content as Grid;
var text = grid.Children[1] as TextBlock;
if (text.Text=="ON")
{
_mainWindow.holdingRegister.hvOut = (ushort)(_mainWindow.holdingRegister.hvOut & ~(1 << int.Parse(grid.Tag.ToString())));
}
else if (text.Text == "OFF")
{
_mainWindow.holdingRegister.hvOut = (ushort)(_mainWindow.holdingRegister.hvOut | (1 << int.Parse(grid.Tag.ToString())));
}
await _mainWindow.WriteToSerialAsync("hvoClick");
}
}
private async void lvoClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var grid= button.Content as Grid;
var stack= button.Content as StackPanel;
if (grid!=null)
{
var text = grid.Children[1] as TextBlock;
if (text.Text == "ON")
{
_mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut & ~(1 << int.Parse(grid.Tag.ToString())));
}
else if (text.Text == "OFF")
{
_mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut | (1 << int.Parse(grid.Tag.ToString())));
}
}
else if(stack != null)
{
var text = stack.Children[1] as TextBlock;
if (text.Text == "ON")
{
_mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut & ~(1 << int.Parse(stack.Tag.ToString())));
}
else if (text.Text == "OFF")
{
_mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut | (1 << int.Parse(stack.Tag.ToString())));
}
}
await _mainWindow.WriteToSerialAsync("lvoClick");
}
}
private async void resetErrorClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
_mainWindow.holdingRegister.resetError = (ushort)(_mainWindow.holdingRegister.resetError | (1 << 0));
await _mainWindow.WriteToSerialAsync("resetErrorClick");
}
}
private async void ChangeTempMode(object sender, RoutedEventArgs e)
{
float number =0;
if (sender is Border border)
{
if (border.Tag.ToString()=="t1")
{
number = float.Parse(t1Text.Text);
}
else if(border.Tag.ToString() == "t2")
{
number = float.Parse(t2Text.Text);
}
else if (border.Tag.ToString() == "t3")
{
number = float.Parse(t3Text.Text);
}
else if (border.Tag.ToString() == "t4")
{
number = float.Parse(t4Text.Text);
}
var parent = border.Parent as StackPanel;
var brother = parent.Children[1] as Border;
List<TextBlock> allTexts= new ();
if (brother.Tag?.ToString() == "t1")
{
allTexts.Add(t1Container.Children[0] as TextBlock);
allTexts.Add(t1Container.Children[1] as TextBlock);
allTexts.Add(t1Container.Children[2] as TextBlock);
}
else if (brother.Tag?.ToString() == "t2")
{
allTexts.Add(t2Container.Children[0] as TextBlock);
allTexts.Add(t2Container.Children[1] as TextBlock);
allTexts.Add(t2Container.Children[2] as TextBlock);
}
else if (brother.Tag?.ToString() == "t3")
{
allTexts.Add(t3Container.Children[0] as TextBlock);
allTexts.Add(t3Container.Children[1] as TextBlock);
allTexts.Add(t3Container.Children[2] as TextBlock);
}
else if (brother.Tag?.ToString() == "t4")
{
allTexts.Add(t4Container.Children[0] as TextBlock);
allTexts.Add(t4Container.Children[1] as TextBlock);
allTexts.Add(t4Container.Children[2] as TextBlock);
}
var button=border.Child as Button;
if (button.Content.ToString()=="M")
{
allTexts[0].Foreground = Brush.Parse("#231f20"); // black
allTexts[1].Foreground = Brush.Parse("#af196f"); // pink
allTexts[2].Foreground = Brush.Parse("#231f20"); // black
button.Foreground = Brush.Parse("#af196f");
button.Content = "A";
if (button.Tag.ToString() == "t1")
{
_mainWindow.holdingRegister.setTemp1 = (int)(number * 10);
}
else if (button.Tag.ToString() == "t2")
{
_mainWindow.holdingRegister.setTemp2 = (int)(number * 10);
}
else if (button.Tag.ToString() == "t3")
{
_mainWindow.holdingRegister.setTemp3 = (int)(number * 10);
}
else if (button.Tag.ToString() == "t4")
{
_mainWindow.holdingRegister.setTemp4 = (int)(number * 10);
}
await _mainWindow.WriteToSerialAsync("DiagnosticsTemp");
}
else
{
foreach (var item in allTexts)
{
item.Foreground = Brush.Parse("#808080"); //gray
}
button.Foreground = Brush.Parse("#4d4d4d");
button.Content = "M";
if (button.Tag.ToString()=="t1")
{
_mainWindow.holdingRegister.setTemp1 = -10000;
}
else if (button.Tag.ToString() == "t2")
{
_mainWindow.holdingRegister.setTemp2 = -10000;
}
else if (button.Tag.ToString() == "t3")
{
_mainWindow.holdingRegister.setTemp3 = -10000;
}
else if (button.Tag.ToString() == "t4")
{
_mainWindow.holdingRegister.setTemp4 = -10000;
}
await _mainWindow.WriteToSerialAsync("DiagnosticsTemp");
}
}
else if(sender is Button btn)
{
if (btn.Tag.ToString() == "t1")
{
number = float.Parse(t1Text.Text);
}
else if (btn.Tag.ToString() == "t2")
{
number = float.Parse(t2Text.Text);
}
else if (btn.Tag.ToString() == "t3")
{
number = float.Parse(t3Text.Text);
}
else if (btn.Tag.ToString() == "t4")
{
number = float.Parse(t4Text.Text);
}
var border1 = btn.Parent as Border;
var parent = border1.Parent as StackPanel;
var brother = parent.Children[1] as Border;
List<TextBlock> allTexts = new();
if (brother.Tag?.ToString() == "t1")
{
allTexts.Add(t1Container.Children[0] as TextBlock);
allTexts.Add(t1Container.Children[1] as TextBlock);
allTexts.Add(t1Container.Children[2] as TextBlock);
}
else if (brother.Tag?.ToString() == "t2")
{
allTexts.Add(t2Container.Children[0] as TextBlock);
allTexts.Add(t2Container.Children[1] as TextBlock);
allTexts.Add(t2Container.Children[2] as TextBlock);
}
else if (brother.Tag?.ToString() == "t3")
{
allTexts.Add(t3Container.Children[0] as TextBlock);
allTexts.Add(t3Container.Children[1] as TextBlock);
allTexts.Add(t3Container.Children[2] as TextBlock);
}
else if (brother.Tag?.ToString() == "t4")
{
allTexts.Add(t4Container.Children[0] as TextBlock);
allTexts.Add(t4Container.Children[1] as TextBlock);
allTexts.Add(t4Container.Children[2] as TextBlock);
}
var button = border1.Child as Button;
if (button.Content.ToString() == "M")
{
allTexts[0].Foreground = Brush.Parse("#231f20"); // black
allTexts[1].Foreground = Brush.Parse("#af196f"); // pink
allTexts[2].Foreground = Brush.Parse("#231f20"); // black
button.Foreground = Brush.Parse("#af196f");
button.Content = "A";
if (button.Tag.ToString() == "t1")
{
_mainWindow.holdingRegister.setTemp1 = (int)(number * 10);
}
else if (button.Tag.ToString() == "t2")
{
_mainWindow.holdingRegister.setTemp2 = (int)(number * 10);
}
else if (button.Tag.ToString() == "t3")
{
_mainWindow.holdingRegister.setTemp3 = (int)(number * 10);
}
else if (button.Tag.ToString() == "t4")
{
_mainWindow.holdingRegister.setTemp4 = (int)(number * 10);
}
await _mainWindow.WriteToSerialAsync("DiagnosticsTemp");
}
else
{
foreach (var item in allTexts)
{
item.Foreground = Brush.Parse("#808080"); //gray
}
button.Foreground = Brush.Parse("#4d4d4d");
button.Content = "M";
if (button.Tag.ToString() == "t1")
{
_mainWindow.holdingRegister.setTemp1 = -10000;
}
else if (button.Tag.ToString() == "t2")
{
_mainWindow.holdingRegister.setTemp2 = -10000;
}
else if (button.Tag.ToString() == "t3")
{
_mainWindow.holdingRegister.setTemp3 = -10000;
}
else if (button.Tag.ToString() == "t4")
{
_mainWindow.holdingRegister.setTemp4 = -10000;
}
await _mainWindow.WriteToSerialAsync("DiagnosticsTemp");
}
}
}
private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e)
{
if (isNegative)
{
targetText.Text = "-" + oldValue.ToString("0.0");
}
else
{
targetText.Text = "+" + oldValue.ToString("0.0");
}
keyBoardPopup.IsVisible = false;
}
private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e)
{
e.Handled = true;
}
private void OnKeyClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if ((button.Content=="+"|| button.Content == "-")&& targetText.Text.Length>0)
{
}
else if((targetText.Text.Length==0 && button.Content == ".")||(targetText.Text.Contains(".")&& button.Content == "."))
{
}
else
{
targetText.Text += button.Content;
}
}
}
private void OnBackClick(object? sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(targetText.Text))
{
// Remove the last character from the text box
targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1);
//number = number.Remove(number.Length - 1);
}
}
private async void EnterClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
bool canEdit = targetButton.Content == "A";
if (!string.IsNullOrEmpty(targetText.Text))
{
float number = float.Parse(targetText.Text);
if (char.IsDigit(targetText.Text[0]))
{
targetText.Text = "+" + number.ToString("0.0");
}
else
{
targetText.Text = number.ToString("0.0");
}
var machine = _machine.ReadMachine();
if (button.Tag.ToString() == "t1")
{
if (canEdit)
{
_mainWindow.holdingRegister.setTemp1 = (int)(number * 10);
}
machine.setTemp1 = number;
}
else if (button.Tag.ToString() == "t2")
{
if (canEdit)
{
_mainWindow.holdingRegister.setTemp2 = (int)(number * 10);
}
machine.setTemp2 = number;
}
else if (button.Tag.ToString() == "t3")
{
if (canEdit)
{
_mainWindow.holdingRegister.setTemp3 = (int)(number * 10);
}
machine.setTemp3 = number;
}
else if (button.Tag.ToString() == "t4")
{
if (canEdit)
{
_mainWindow.holdingRegister.setTemp4 = (int)(number * 10);
}
machine.setTemp4 = number;
}
_machine.UpdateMachine(machine);
getUiElementes();
if (canEdit)
{
await _mainWindow.WriteToSerialAsync("DiagnosticsEnter");
}
keyBoardPopup.IsVisible = false;
}
}
}
private void ShowNumberKeyBoard(object? sender, PointerPressedEventArgs e)
{
if (sender is Border border)
{
var parent = border.Parent as StackPanel;
var brother = parent.Children[0] as Border;
targetButton = brother.Child as Button;
if (border.Tag?.ToString() == "t1")
{
targetText = t1Text;
}
else if (border.Tag?.ToString() == "t2")
{
targetText = t2Text;
}
else if (border.Tag?.ToString() == "t3")
{
targetText = t3Text;
}
else if (border.Tag?.ToString() == "t4")
{
targetText = t4Text;
}
enterBtn.Tag = border.Tag;
isNegative = targetText.Text.StartsWith("-");
oldValue = float.Parse(targetText.Text.Substring(1));
targetText.Text = "";
keyBoardPopup.IsVisible = true;
}
}
private async void OnIgnorePidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
pidPopupOverlay.IsVisible = false;
}
private async void showInnerPid(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var configratipn = _configration.ReadConfigrationById(button.Tag.ToString());
pidPopupOverlay.IsVisible = false;
header.Text = button.Content.ToString();
header.Tag = button.Tag;
// Set slider values instead of text box values
kpSlider.Value = configratipn.kp;
kiSlider.Value = configratipn.ki;
kdSlider.Value = configratipn.kd;
klSlider.Value = configratipn.kl;
// Update the display values
kpSliderValue.Text = configratipn.kp.ToString();
kiSliderValue.Text = configratipn.ki.ToString();
kdSliderValue.Text = configratipn.kd.ToString();
klSliderValue.Text = configratipn.kl.ToString();
fcThreshold.Text = configratipn.FC_Threshold.ToString("0.0");
heatConRange.Text = configratipn.HeatConRange.ToString("0.0");
innerPidPopupOverlay.IsVisible = true;
}
}
private async void OnIgnoreInnerPidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
innerPidPopupOverlay.IsVisible = false;
pidPopupOverlay.IsVisible = true;
}
private void OnKeyUp(object? sender, KeyEventArgs e)
{
if (sender is TextBox textBox)
{
if (textBox != null && float.TryParse(textBox.Text, out float value))
{
if (textBox.Name == "heatConRange")
{
if (value > 25.0)
{
textBox.Text = "25.0";
}
}
else
{
if (value > 100)
{
textBox.Text = "100";
}
}
// Check if the value exceeds 100 and reset to 100 if necessary.
}
}
}
private async void YesBtnClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var configration = _configration.ReadConfigrationById(header.Tag.ToString());
if (configration!=null)
{
// Read values from sliders instead of text boxes
configration.kp = (int)kpSlider.Value;
configration.ki = (int)kiSlider.Value;
configration.kd = (int)kdSlider.Value;
configration.kl = (int)klSlider.Value;
if (string.IsNullOrEmpty(fcThreshold.Text))
{
configration.FC_Threshold = 0;
}
else
{
configration.FC_Threshold = float.Parse(fcThreshold.Text);
}
if (string.IsNullOrEmpty(heatConRange.Text))
{
configration.HeatConRange = 1.0F;
}
else
{
if (float.TryParse(heatConRange.Text, out float value))
{
if (value<1.0)
{
configration.HeatConRange = 1.0F;
}
else
{
configration.HeatConRange = float.Parse(heatConRange.Text);
}
}
else
{
configration.HeatConRange = 1.0F;
}
}
_configration.UpdateConfigration(configration);
_mainWindow.reSendHolding = true;
CloseKeyboard();
innerPidPopupOverlay.IsVisible = false;
pidPopupOverlay.IsVisible = true;
}
}
}
private void CloseKeyboard()
{
try
{
if (_keyboardProcess != null)
{
// Kill the keyboard process
_keyboardProcess.Kill();
_keyboardProcess.Dispose();
_keyboardProcess = null;
// Force kill any remaining keyboard processes
var processKill = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "killall",
Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards
UseShellExecute = false,
CreateNoWindow = true
}
};
processKill.Start();
processKill.WaitForExit(1000);
processKill.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error closing keyboard: {ex.Message}");
}
}
private (string? fileName, string args) GetKeyboardCommand()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return ("osk.exe", "");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return ("onboard", ""); // or "florence", "matchbox-keyboard"
return (null, "");
}
private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e)
{
if (_keyboardProcess is { HasExited: false })
return;
var (fileName, args) = GetKeyboardCommand();
if (fileName is null)
return;
_keyboardProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = args,
UseShellExecute = true,
WorkingDirectory = "/usr/bin"
},
EnableRaisingEvents = true
};
try
{
_keyboardProcess.Start();
Dispatcher.UIThread.Post(() =>
{
if (sender is Border border)
{
var textbox = border.Child as TextBox;
textbox.SelectionStart = 0;
textbox.SelectionEnd = textbox.Text?.Length ?? 0;
}
});
}
catch
{
// fail silently if keyboard not found
}
}
private void OnTextInput(object? sender, TextInputEventArgs e)
{
if (sender is TextBox textBox)
{
string newText = textBox.Text + e.Text;
if (!Regex.IsMatch(newText, @"^\d*\.?\d*$"))
{
e.Handled = true;
}
}
}
private void OnTextInputOnlyInteager(object? sender, TextInputEventArgs e)
{
if (sender is TextBox textBox)
{
string newText = textBox.Text + e.Text;
if (!Regex.IsMatch(newText, @"^\d*$"))
{
e.Handled = true;
}
}
}
private async void showPidPopUp(object? sender, RoutedEventArgs e)
{
pidPopupOverlay.IsVisible = true;
}
private void getUiElementes()
{
var error = _error.ReadErrorSettings()[0];
if (error.phaseNumber == 1)
{
phaseContainer.Background = Avalonia.Media.Brushes.Gray;
phaseContainer.IsEnabled = false;
}
else
{
phaseContainer.Background = Brush.Parse("#E6E6E6");
phaseContainer.IsEnabled = true;
}
flagRectangles = this.GetLogicalDescendants()
.OfType<Rectangle>()
.Where(cb => cb.Classes.Contains("flag"))
.ToList();
InputesElements = this.GetLogicalDescendants()
.OfType<Control>()
.Where(c => c.Classes.Contains("in") && (c is Grid || c is Ellipse))
.ToList();
MotoreState = this.GetLogicalDescendants()
.OfType<Control>()
.Where(c => c.Classes.Contains("motorState") && (c is Grid || c is Ellipse))
.ToList();
hvoOutPuts = this.GetLogicalDescendants()
.OfType<Control>()
.Where(c => c.Classes.Contains("hvo") && (c is Grid || c is Ellipse))
.ToList();
lvoOutPuts = this.GetLogicalDescendants()
.OfType<Control>()
.Where(c => c.Classes.Contains("lvo") && (c is Grid||c is StackPanel || c is Ellipse))
.ToList();
var machine=_machine.ReadMachine();
t1Text.Text = char.IsDigit(machine.setTemp1.ToString()[0])?"+"+ machine.setTemp1.ToString(): machine.setTemp1.ToString();
t2Text.Text = char.IsDigit(machine.setTemp2.ToString()[0]) ? "+" + machine.setTemp2.ToString() : machine.setTemp2.ToString();
t3Text.Text = char.IsDigit(machine.setTemp3.ToString()[0]) ? "+" + machine.setTemp3.ToString() : machine.setTemp3.ToString();
t4Text.Text = char.IsDigit(machine.setTemp4.ToString()[0]) ? "+" + machine.setTemp4.ToString() : machine.setTemp4.ToString();
}
private void setDefaultSettings()
{
var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel;
_mainWindow.minimizeBtn.IsVisible = false;
if (_isFromManualControl)
{
// Special UI setup when called from ManualControl
_mainWindow.HomeTrack.IsVisible = true;
_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = true;
_mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
_mainWindow.ManualControlTrack.IsVisible = true;
_mainWindow.ManualControlPolygon.Stroke = Avalonia.Media.Brushes.Black;
}
else
{
// Original logic for other callers
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
//_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = false;
_mainWindow.RecipeEditTrack.IsVisible = false;
if (_isAdvSettings)
{
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = true;
_mainWindow.AdvanceSettingsPolygon.Stroke = Avalonia.Media.Brushes.Black;
}
else
{
_mainWindow.SettingTrack.IsVisible = true;
_mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
}
}
_mainWindow.DiagnosticsTrack.IsVisible = true;
_mainWindow.DiagnosticsPolygon.Stroke = Brush.Parse("#A4275D");
// Remove the button from its current position
stackPanel.Children.Remove(_mainWindow.DiagnosticsTrack);
// Add it back at the end of the StackPanel
stackPanel.Children.Add(_mainWindow.DiagnosticsTrack);
_mainWindow.TitleBtn.IsVisible = false;
_mainWindow.TitleBtn.IsVisible = true;
_mainWindow.Title.Text = "DMC7A";
//Set Footer
_mainWindow.footerMsg.IsVisible = true;
_mainWindow.footerMsg.Text= "Read Values, And Control Outputs Manually";
_mainWindow.footerMsg.Foreground= Brush.Parse("#A4275D");
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = false;
}
// KP Slider and Button Event Handlers
private void KpSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (kpSliderValue != null && sender is Slider slider)
{
kpSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KpMinusClick(object? sender, RoutedEventArgs e)
{
if (kpSlider.Value > kpSlider.Minimum)
{
kpSlider.Value--;
}
}
private void KpPlusClick(object? sender, RoutedEventArgs e)
{
if (kpSlider.Value < kpSlider.Maximum)
{
kpSlider.Value++;
}
}
// KI Slider and Button Event Handlers
private void KiSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (kiSliderValue != null && sender is Slider slider)
{
kiSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KiMinusClick(object? sender, RoutedEventArgs e)
{
if (kiSlider.Value > kiSlider.Minimum)
{
kiSlider.Value--;
}
}
private void KiPlusClick(object? sender, RoutedEventArgs e)
{
if (kiSlider.Value < kiSlider.Maximum)
{
kiSlider.Value++;
}
}
// KD Slider and Button Event Handlers
private void KdSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (kdSliderValue != null && sender is Slider slider)
{
kdSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KdMinusClick(object? sender, RoutedEventArgs e)
{
if (kdSlider.Value > kdSlider.Minimum)
{
kdSlider.Value--;
}
}
private void KdPlusClick(object? sender, RoutedEventArgs e)
{
if (kdSlider.Value < kdSlider.Maximum)
{
kdSlider.Value++;
}
}
// KL Slider and Button Event Handlers
private void KlSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (klSliderValue != null && sender is Slider slider)
{
klSliderValue.Text = ((int)slider.Value).ToString();
}
}
private void KlMinusClick(object? sender, RoutedEventArgs e)
{
if (klSlider.Value > klSlider.Minimum)
{
klSlider.Value--;
}
}
private void KlPlusClick(object? sender, RoutedEventArgs e)
{
if (klSlider.Value < klSlider.Maximum)
{
klSlider.Value++;
}
}
}
============================================================
FILE: DaireApplication/Views/UserController/Home.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="DaireApplication.Home"
Width="1280" Height="620" >
<Grid RowDefinitions="*">
<!--Main Body-->
<Grid Grid.Row="0" ColumnDefinitions="Auto,*" >
<Grid Grid.Column="1" HorizontalAlignment="Center"
VerticalAlignment="Center" Height="698" Width="465" >
<Grid x:Name="machinePic" IsVisible="True">
<Grid.Background >
<ImageBrush Source="/Assets/Machine.png"/>
</Grid.Background>
</Grid>
<Grid x:Name="CalcGrid" MaxWidth="350" MaxHeight="500" IsVisible="False">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"></Setter>
<Setter Property="CornerRadius" Value="20"></Setter>
<Setter Property="Width" Value="100"></Setter>
<Setter Property="Height" Value="100"></Setter>
<Setter Property="FontSize" Value="50"></Setter>
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Background" Value="White"></Setter>
<Setter Property="CornerRadius" Value="20"></Setter>
<Setter Property="RenderTransform" Value="scale(1.11)"></Setter>
</Style>
</Grid.Styles>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- TextBox for Input -->
<TextBox x:Name="InputTextBox" Grid.Row="0" Width="300" Height="50" FontSize="20" HorizontalAlignment="Center" Margin="10" IsReadOnly="True" PasswordChar="*"/>
<!-- Keypad Grid -->
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!-- Number Buttons -->
<Button Content="1" Grid.Row="0" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="2" Grid.Row="0" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="3" Grid.Row="0" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="4" Grid.Row="1" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="5" Grid.Row="1" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="6" Grid.Row="1" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="7" Grid.Row="2" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="8" Grid.Row="2" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button Content="9" Grid.Row="2" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<!-- Control Buttons -->
<Button Content="BACK" Grid.Row="3" Grid.Column="0" FontSize="20" Background="#D3D3D3" Margin="5" Click="OnBackClick" />
<Button Content="0" Grid.Row="3" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick" />
<Button x:Name="loginBtn" Content="ENTER" Grid.Row="3" Grid.Column="2" FontSize="20" Background="#A4275D" Foreground="White" Margin="5" Click="LogIn" />
</Grid>
</Grid>
</Grid>
<Grid Grid.Column="0" RowDefinitions="Auto,1.5*">
<StackPanel Margin="10,50,0,10" Grid.Row="0" HorizontalAlignment="Center" >
<Label Foreground="Black" FontSize="30" FontWeight="Normal" >USER SELECTION</Label>
</StackPanel>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Margin="0,0">
<Grid x:Name="DynamicGrid">
<!-- Define three columns -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"></Setter>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="RenderTransform" Value="scale(1.11)"></Setter>
<Setter Property="Background" Value="White"></Setter>
</Style>
</Grid.Styles>
<!-- Dynamic rows will be generated programmatically in code-behind -->
</Grid>
</ScrollViewer>
</Grid>
</Grid>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/Home.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
using AvaloniaApplication1.DataBase;
using DaireApplication.DataBase;
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace DaireApplication;
public partial class Home : UserControl
{
private Button? _previousButton;
private Button? currentButton;
private UserTable _userRepo = new UserTable();
private MainWindow? _mainWindow;
public Home()
{
}
public Home(MainWindow mainWindow)
{
_mainWindow = mainWindow;
InitializeComponent();
// Migrate legacy data to AppData directory
DataPathManager.MigrateLegacyData();
setDefaultSettings();
setDefaultUsers();
setDefaultRecipe();
setDefaultMachine();
SetDefaultMapping();
SetDefaultConfigration();
SetDefaultScreen();
SetDefaultErrorSettings();
addDynamicButtons();
_mainWindow.UserName.Holding -=Admin.CloseApplication;
}
private async void OnUserButtonClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button) // Ensure the sender is the button that triggered the event
{
currentButton = button;
if (_previousButton != null)
{
if (_previousButton == button)
{
if (button.Tag=="1")
{
CalcGrid.IsVisible = !CalcGrid.IsVisible;
machinePic.IsVisible = !machinePic.IsVisible;
return;
}
else
{
loginBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
}
ResetButtonColor(_previousButton);
}
var textBlock = button.Content as TextBlock;
if (textBlock != null)
{
textBlock.Foreground = Avalonia.Media.Brushes.DeepPink;
}
button.BorderBrush = Avalonia.Media.Brushes.DeepPink;
button.BorderThickness = new Thickness(3);
_previousButton = button;
if (button.Tag == "1")
{
CalcGrid.IsVisible = !CalcGrid.IsVisible;
machinePic.IsVisible = !machinePic.IsVisible;
}
else
{
loginBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
//CalcGrid.IsVisible = !CalcGrid.IsVisible;
//machinePic.IsVisible = !machinePic.IsVisible;
}
//End UI...
}
private void LogIn(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var users = _userRepo.ReadUsers();
string inputText = InputTextBox.Text;
foreach (var item in users)
{
if (currentButton.Content is Grid grid)
{
if (grid.Children[0] is TextBlock textBlock)
{
if (textBlock.Text == item.UserName)
{
if (item.IsActive)
{
if (inputText == item.Password)
{
var userName = _mainWindow.FindControl<Button>("UserName");
userName.Content = item.UserName;
Program.currentUser = item;
if (item.IsAdmin == true)
{
_mainWindow.holdingRegister.resetError = 0;
_mainWindow.restBoard = true;
_mainWindow.FindControl<ContentControl>("ContentArea").Content = new Admin(_mainWindow, item);
return;
}
else
{
_mainWindow.FindControl<ContentControl>("ContentArea").Content = new Recipe(_mainWindow, item);
InputTextBox.Text = string.Empty;
return;
}
}
else
{
_mainWindow.TextCenter.HorizontalAlignment = HorizontalAlignment.Center;
_mainWindow.footerMsg.Text = "Wrong Password!!";
_mainWindow.footerMsg.IsVisible = true;
_mainWindow.footer.Background = Avalonia.Media.Brushes.Red;
_mainWindow.footerMsg.Foreground = Avalonia.Media.Brushes.White;
_mainWindow.footerMsg.HorizontalAlignment = HorizontalAlignment.Center;
_mainWindow.footerDateContainer.IsVisible = false;
_mainWindow.footerStartBtn.IsVisible = false;
}
}
else
{
var userName = _mainWindow.FindControl<Button>("UserName");
userName.Content = item.UserName;
Program.currentUser = item;
if (item.IsAdmin == true)
{
_mainWindow.holdingRegister.resetError = 0;
_mainWindow.restBoard = true;
_mainWindow.FindControl<ContentControl>("ContentArea").Content = new Admin(_mainWindow, item);
return;
}
else
{
_mainWindow.FindControl<ContentControl>("ContentArea").Content = new Recipe(_mainWindow, item);
InputTextBox.Text = string.Empty;
return;
}
}
}
}
}
}
}
// Display or use the input text
// Clear the text after showing the message
InputTextBox.Text = string.Empty;
}
private void OnKeyClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
// Append the button's content to the input box
InputTextBox.Text += button.Content?.ToString();
}
}
private void OnBackClick(object? sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(InputTextBox.Text))
{
// Remove the last character from the text box
InputTextBox.Text = InputTextBox.Text.Remove(InputTextBox.Text.Length - 1);
}
}
private void ResetButtonColor(Button button)
{
button.BorderBrush = Avalonia.Media.Brushes.White;
var textBlock = button.Content as TextBlock;
if (textBlock != null)
{
textBlock.Foreground = Avalonia.Media.Brushes.Black;
}
// Reset the color of the TextBlock inside the button
}
private void addDynamicButtons()
{
var users = _userRepo.ReadUsers();
var grid = this.FindControl<Grid>("DynamicGrid");
int userIdex = 0;
if (users.Count < 2)
{
for (int i = 0; i < (int)Math.Ceiling((double)users.Count / 2); i++) // Example: 20 rows
{
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// Add content for each column
for (int col = 0; col < 2; col++)
{
// StackPanel for the LED indicator dots
var indicatorPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(10),
Spacing = 10
};
// Adding the indicator dots dynamically
if (users[userIdex + col].IsAdmin)
{
var colors = new[] { Brush.Parse("#A4275D"), Brush.Parse("#A4275D"), Brush.Parse("#A4275D") };
foreach (var color in colors)
{
indicatorPanel.Children.Add(new Rectangle
{
Width = 30,
Height = 10,
Fill = color,
RadiusX = 3,
RadiusY = 3,
Margin = new Thickness(3),
VerticalAlignment = VerticalAlignment.Bottom,
});
}
}
else if (users[userIdex + col].CanEdit)
{
var colors = new[] { Brush.Parse("#A4275D"), Brush.Parse("#A4275D") };
foreach (var color in colors)
{
indicatorPanel.Children.Add(new Rectangle
{
Width = 30,
Height = 10,
Fill = color,
RadiusX = 3,
RadiusY = 3,
Margin = new Thickness(3),
VerticalAlignment = VerticalAlignment.Bottom,
});
}
}
else
{
var colors = new[] { Brush.Parse("#A4275D") };
foreach (var color in colors)
{
indicatorPanel.Children.Add(new Rectangle
{
Width = 30,
Height = 10,
Fill = color,
RadiusX = 3,
RadiusY = 3,
Margin = new Thickness(3),
VerticalAlignment = VerticalAlignment.Bottom,
});
}
}
// Create a Grid for button content with two rows:
// Row 0 (star) holds the text (centered) and Row 1 (auto) holds the indicator dots at the bottom.
var buttonContent = new Grid();
buttonContent.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
buttonContent.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// TextBlock centered in first row
var textBlock = new TextBlock
{
Padding = new Thickness(10),
Text = users[userIdex + col].UserName,
FontSize = 40,
FontWeight = FontWeight.Normal,
Foreground = Avalonia.Media.Brushes.Black,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
};
// Place the text in the first row
Grid.SetRow(textBlock, 0);
// Place the indicator panel in the second row
Grid.SetRow(indicatorPanel, 1);
// Add both elements to the grid
buttonContent.Children.Add(textBlock);
buttonContent.Children.Add(indicatorPanel);
// Create the button with the new content layout
var button = new Button
{
Width = 290,
Height = 190,
Margin = new Thickness(10),
Content = buttonContent,
Tag = users[userIdex + col].IsActive ? "1" : "0",
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Bottom,
};
button.Click += OnUserButtonClick;
grid.Children.Add(button);
Grid.SetRow(button, i);
Grid.SetColumn(button, col);
}
userIdex += 2;
}
}
else
{
for (int i = 0; i < (int)Math.Ceiling((double)users.Count / 2); i++) // Example: 20 rows
{
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// Add content for each column
for (int col = 0; col < 2; col++)
{
// StackPanel for the LED indicator dots
var indicatorPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(10),
Spacing = 10
};
// Adding the indicator dots dynamically
if (users[userIdex + col].IsAdmin)
{
var colors = new[] { Brush.Parse("#A4275D"), Brush.Parse("#A4275D"), Brush.Parse("#A4275D") };
foreach (var color in colors)
{
indicatorPanel.Children.Add(new Rectangle
{
Width = 30,
Height = 10,
Fill = color,
RadiusX = 3,
RadiusY = 3,
Margin = new Thickness(3),
VerticalAlignment = VerticalAlignment.Bottom,
});
}
}
else if (users[userIdex + col].CanEdit)
{
var colors = new[] { Brush.Parse("#A4275D"), Brush.Parse("#A4275D") };
foreach (var color in colors)
{
indicatorPanel.Children.Add(new Rectangle
{
Width = 30,
Height = 10,
Fill = color,
RadiusX = 3,
RadiusY = 3,
Margin = new Thickness(3),
VerticalAlignment = VerticalAlignment.Bottom,
});
}
}
else
{
var colors = new[] { Brush.Parse("#A4275D") };
foreach (var color in colors)
{
indicatorPanel.Children.Add(new Rectangle
{
Width = 30,
Height = 10,
Fill = color,
RadiusX = 3,
RadiusY = 3,
Margin = new Thickness(3),
VerticalAlignment = VerticalAlignment.Bottom,
});
}
}
// Create a Grid for button content with two rows:
// Row 0 (star) holds the text (centered) and Row 1 (auto) holds the indicator dots at the bottom.
var buttonContent = new Grid();
buttonContent.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });
buttonContent.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// TextBlock centered in first row
var textBlock = new TextBlock
{
Padding = new Thickness(10),
Text = users[userIdex + col].UserName,
FontSize = 40,
FontWeight = FontWeight.Normal,
Foreground = Avalonia.Media.Brushes.Black,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
};
// Place the text in the first row
Grid.SetRow(textBlock, 0);
// Place the indicator panel in the second row
Grid.SetRow(indicatorPanel, 1);
// Add both elements to the grid
buttonContent.Children.Add(textBlock);
buttonContent.Children.Add(indicatorPanel);
// Create the button with the new content layout
var button = new Button
{
Width = 290,
Height = 190,
Margin = new Thickness(10),
Tag = users[userIdex + col].IsActive ? "1" : "0",
Content = buttonContent,
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Bottom,
};
button.Click += OnUserButtonClick;
grid.Children.Add(button);
Grid.SetRow(button, i);
Grid.SetColumn(button, col);
}
userIdex += 2;
}
}
}
private void setDefaultUsers()
{
string filePath = DataPathManager.GetDataFilePath("Users.csv");
List<UserTable> users = new List<UserTable>();
if (!File.Exists(filePath))
{
string csvHeader = "ID,UserName,Password,CanEdit,IsAdmin,IsActive";
users.Add(new UserTable
{
Id = 1,
UserName = "ADMIN",
Password = "1111",
CanEdit = true,
IsAdmin = true,
IsActive=false
}
);
users.Add(new UserTable
{
Id = 2,
UserName = "CHEF",
Password = "2222",
CanEdit = true,
IsAdmin = false,
IsActive = false
}
);
users.Add(new UserTable
{
Id = 3,
UserName = "OPERATOR1",
Password = "3333",
CanEdit = false,
IsAdmin = false,
IsActive = false
}
);
users.Add(new UserTable
{
Id = 4,
UserName = "OPERATOR2",
Password = "4444",
CanEdit = false,
IsAdmin = false,
IsActive = false
}
);
List<string> lines = new List<string>();
foreach (var item in users)
{
lines.Add(string.Join(",", [item.Id, item.UserName, item.Password, item.CanEdit ? "1" : "0", item.IsAdmin ? "1" : "0",item.IsActive?"1":"0"]));
}
File.WriteAllLines(filePath, new string[] { csvHeader });
File.AppendAllLines(filePath, lines);
}
}
private void setDefaultRecipe()
{
string filePath = DataPathManager.GetDataFilePath("Recipe.csv");
List<RecipeTable> recipes = new List<RecipeTable>();
if (!File.Exists(filePath))
{
string csvHeader = "ID,Name,TankTemp,FountainTemp,Mixer,Fountain,MoldHeater,Vibration,VibHeater,Pedal,PedalOnTime,PedalOffTime,HeatingGoal,CoolingGoal,PouringGoal";
recipes.Add(new RecipeTable
{
Id = 1,
Name = "MILK",
Mixer = false,
Fountain = false,
MoldHeater = false,
Vibration = false,
VibHeater = false,
Pedal = false
}
);
List<string> lines = new List<string>();
foreach (var item in recipes)
{
if (item != null)
{
lines.Add(string.Join(",", [1, item.Name, item.TankTemp, item.FountainTemp, item.Mixer.Value ? "1" : "0", item.Fountain.Value ? "1" : "0", item.MoldHeater.Value ? "1" : "0", item.Vibration.Value ? "1" : "0", item.VibHeater.Value ? "1" : "0", item.Pedal.Value ? "1" : "0", item.PedalOnTime, item.PedalOffTime, item.HeatingGoal, item.CoolingGoal, item.PouringGoal]));
}
}
File.WriteAllLines(filePath, new string[] { csvHeader });
File.AppendAllLines(filePath, lines);
}
}
private void setDefaultMachine()
{
string filePath = DataPathManager.GetDataFilePath("Machine.csv");
MachineTable machine = new MachineTable();
if (!File.Exists(filePath))
{
string csvHeader = "ID,TankMaxHeat,PumbMaxHeat,PumbDelay,MixerDelay,HeatingDelay,CoolingDelay,PouringDelay,PumbMinHeat,AbsMaxTemp,AbsMinTemp,PreHeatingTemp,SetTemp1,SetTemp2,SetTemp3,SetTemp4";
string line = string.Join(",", ["1", machine.TankMaxHeat, machine.PumbMaxHeat, machine.PumbDelay, machine.MixerDelay, machine.HeatingDelay, machine.CoolingDelay, machine.PouringDelay, machine.PumbMinHeat, machine.AbsMaxHeat, machine.AbsMinHeat, machine.PreHeatingTemp, machine.setTemp1, machine.setTemp2, machine.setTemp3, machine.setTemp4]);
File.WriteAllLines(filePath, new string[] { csvHeader });
File.AppendAllText(filePath, line);
}
}
private void SetDefaultMapping()
{
string filePath = DataPathManager.GetDataFilePath("Mapping.csv");
if (!File.Exists(filePath))
{
string csvHeader = "Id,Name,Address,IsRead,BitNumbers";
string[] defaultMappings =
{
string.Join(",", "1", "Pedal", "1", "1", "0"),
string.Join(",", "2", "Cover Sensor", "1", "1", "1"),
string.Join(",", "3", "E-Stop", "1", "1", "2"),
string.Join(",", "4", "Tank Bottom Temp", "8", "1", "8"),
string.Join(",", "5", "Tank Wall Temp", "9", "1", "9"),
string.Join(",", "6", "Pump Temp", "10", "1", "10"),
string.Join(",", "7", "Fountain Temp", "11", "1", "11"),
string.Join(",", "8", "Vibrator Heater", "2", "0", "0"),
string.Join(",", "9", "Mold Heater", "2", "0", "1"),
string.Join(",", "10", "Alarm", "2", "0", "2"),
string.Join(",", "11", "Vibrator", "1", "0", "0"),
string.Join(",", "12", "Water", "1", "0", "1"),
string.Join(",", "13", "Compressor", "1", "0", "2"),
string.Join(",", "14", "HELIX Heater", "1", "0", "3"),
string.Join(",", "15", "Tank Heater Bottom", "1", "0", "4"),
string.Join(",", "16", "Tank Heater Wall", "1", "0", "5"),
string.Join(",", "17", "Mixer", "3", "0", "0"),
string.Join(",", "18", "Helix", "3", "0", "1")
};
File.WriteAllLines(filePath, new[] { csvHeader }.Concat(defaultMappings));
}
}
private void SetDefaultConfigration()
{
string filePath = DataPathManager.GetDataFilePath("Configration.csv");
if (!File.Exists(filePath))
{
string csvHeader = "Id,Max,Min,H_out,FC_out,SC_out,kp,ki,kd,kl,Name,I_Nuet,I_Mot1,I_Mot2,FC_Threshold,HeatConRange";
string[] defaultConfigrations =
{
string.Join(",", "1", $"70", "0", "4", "-1", "-1", "50", "30", "20", "0","Tank Heater Bottom","14","3","3","0.3","10.0"),
string.Join(",", "2", $"70", "0", "5", "-1", "-1", "50", "30", "20", "0","Tank Heater Wall","0","0","0","0.3","10.0"),
string.Join(",", "3", $"70", $"-10", "3", "2|1", "1", "50", "30", "20", "0","HELIX Heater","0","0","0","0.3","10.0"),
string.Join(",", "4", $"70", "0", "3", "2|1", "1", "50", "30", "20", "0","","0","0","0","0.3","5")
};
File.WriteAllLines(filePath, new[] { csvHeader }.Concat(defaultConfigrations));
}
}
private void setDefaultSettings()
{
_mainWindow.minimizeBtn.IsVisible = false;
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
//_mainWindow.HomePolygon.Stroke = Brush.Parse("#A4275D");
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.TitleBtn.IsVisible = false;
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
_mainWindow.SoftwareTrack.IsVisible = false;
_mainWindow.version.IsVisible = false;
_mainWindow.ManualControlTrack.IsVisible = false;
//Set Footer
_mainWindow.footerMsg.Text = "";
_mainWindow.footerMsg.MaxWidth = 1000;
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerMsg.Foreground = Avalonia.Media.Brushes.Black;
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = false;
_mainWindow.chefBtns.IsVisible = false;
}
private void SetDefaultErrorSettings()
{
string filePath = DataPathManager.GetDataFilePath("ErrorSettings.csv");
if (!File.Exists(filePath))
{
ErrorSettingsTable error = new ErrorSettingsTable
{
Id = 1,
gridFreq = 50,
phaseNumber = 3,
extPower = true,
phaseVoltage=220
};
string csvHeader = "Id,gridFreq,phaseNumber,extPower,phaseVoltage";
string line = string.Join(",", new[] { error.Id.ToString(), error.gridFreq.ToString(), error.phaseNumber.ToString(), error.extPower ? "1" : "0", error.phaseVoltage.ToString() });
File.WriteAllLines(filePath, new[] { csvHeader, line });
}
}
private void SetDefaultScreen()
{
string filePath = DataPathManager.GetDataFilePath("Screen.csv");
if (!File.Exists(filePath))
{
ScreeenTable screen = new ScreeenTable
{
Id = 1,
brightness = 100,
dimSec = 3300,
offSec = 3600,
port = "",
boundRate = 19200,
parity = 1,
stopBits = 0,
sendingTime = 50,
warningLimit = 1,
errorLimit = 2
};
string csvHeader = "Id,Brightness,DimSec,OffSec,Port,BoundRate,Parity,StopBits,SendingTime,WarningLimit,ErrorLimit";
string line = string.Join(",", new[] {
screen.Id.ToString(),
screen.brightness.ToString(),
screen.dimSec.ToString(),
screen.offSec.ToString(),
screen.port,
screen.boundRate.ToString(),
screen.parity.ToString(),
screen.stopBits.ToString(),
screen.sendingTime.ToString(),
screen.warningLimit.ToString(),
screen.errorLimit.ToString()
});
File.WriteAllLines(filePath, new[] { csvHeader, line });
}
}
}
============================================================
FILE: DaireApplication/Views/UserController/ManualControl.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="1280"
Height="620"
Background="#B3B3B3"
x:Class="DaireApplication.ManualControl">
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,*">
<Grid Grid.Column="0" RowDefinitions="2*,0.9*,2*" Margin="0,0,-100,0">
<!--1st box-->
<StackPanel Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Center">
<Border
Width="290"
Height="150"
Background="#f9f9f9"
CornerRadius="10"
Padding="5,10">
<StackPanel Spacing="5">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#ff0000"
FontWeight="Medium">HELIX HEATING CONTROL</TextBlock>
<!--Temp Control-->
<StackPanel Orientation="Horizontal" Spacing="5">
<Border
Width="100"
Height="63"
Background="#e6e6e6"
CornerRadius="5"
Padding="5"
Tag="t3"
PointerPressed="ShowNumberKeyBoard">
<StackPanel Spacing="7">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#666666">SET TEMP.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="setHelixText"
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#af196f">+0</TextBlock>
<TextBlock
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#af196f">°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<Border
Width="100"
Height="63"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="7">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#666666">REAL TEMP.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="pumbRealTemp"
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#000000">
0
</TextBlock>
<TextBlock
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#000000">°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Spacing="3">
<Border Width="70"
Height="30"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="9">
<TextBlock FontSize="15"
HorizontalAlignment="Center"
Foreground="#231f20">AUTO</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="60" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
<Border Width="70"
Height="30"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="9">
<TextBlock FontSize="15"
HorizontalAlignment="Center"
Foreground="#231f20">ON/OFF</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="60" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
<Border Width="276"
Height="40"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="13">
<TextBlock
FontSize="19"
Foreground="#231f20"
HorizontalAlignment="Center">HELIX MOTOR ON / OFF</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="265" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
</StackPanel>
</Border>
</StackPanel>
<!--2ed box-->
<StackPanel Grid.Row="1" HorizontalAlignment="Right" >
<Border
Width="290"
Height="55"
Background="#f9f9f9"
CornerRadius="10"
Padding="5">
<StackPanel>
<TextBlock FontSize="15"
Foreground="#800000"
HorizontalAlignment="Center"
FontWeight="Medium">TANK WALL TEMPERETURE</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="tankWallRealTemp"
FontSize="23"
FontWeight="DemiBold"
Foreground="#333333"
>0</TextBlock>
<TextBlock FontSize="23"
FontWeight="DemiBold"
Foreground="#333333"
>°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
</StackPanel>
<!--3rd box-->
<StackPanel Grid.Row="2" HorizontalAlignment="Right" >
<Border
Width="290"
Height="150"
Background="#f9f9f9"
CornerRadius="10"
Padding="5,10">
<StackPanel Spacing="5">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#ff0000"
FontWeight="Medium">TANK HEATING CONTROL</TextBlock>
<!--Temp Control-->
<StackPanel Orientation="Horizontal" Spacing="5">
<Border
Width="100"
Height="63"
Background="#e6e6e6"
CornerRadius="5"
Padding="5"
Tag="t1"
PointerPressed="ShowNumberKeyBoard">
<StackPanel Spacing="7">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#666666">SET TEMP.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="setTankBtmText"
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#af196f">+0</TextBlock>
<TextBlock
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#af196f">°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<Border
Width="100"
Height="63"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="7">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#666666">REAL TEMP.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="tankBtmRealTemp"
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#000000">0</TextBlock>
<TextBlock
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#000000">°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Spacing="3">
<Border Width="70"
Height="30"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="9">
<TextBlock FontSize="15"
HorizontalAlignment="Center"
Foreground="#231f20">AUTO</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="60" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
<Border Width="70"
Height="30"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="9">
<TextBlock FontSize="15"
HorizontalAlignment="Center"
Foreground="#231f20">ON/OFF</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="60" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
<Border Width="276"
Height="40"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="13">
<TextBlock
FontSize="19"
Foreground="#231f20"
HorizontalAlignment="Center">HELIX MOTOR ON / OFF</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="265" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
</StackPanel>
</Border>
</StackPanel>
</Grid>
<Grid Grid.Column="1" Height="596" Width="484">
<Grid.Background >
<ImageBrush Source="/Assets/ManualControlMachine.png" />
</Grid.Background>
</Grid>
<Grid Grid.Column="2" RowDefinitions="*,0*,*,*" HorizontalAlignment="Left">
<Border Width="290"
Height="103"
Background="#f9f9f9"
CornerRadius="10"
HorizontalAlignment="Left"
Margin="-140,0,0,0"
Padding="5">
<StackPanel>
<TextBlock FontSize="15"
Foreground="#0000ff"
FontWeight="Medium"
HorizontalAlignment="Center">CHOCOLATE COOLING CONTROL</TextBlock>
<StackPanel Orientation="Horizontal" Spacing="5">
<Border
Width="100"
Height="63"
Background="#e6e6e6"
CornerRadius="5"
Padding="5"
Tag="t4"
PointerPressed="ShowNumberKeyBoard">
<StackPanel Spacing="7">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#666666">SET TEMP.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="setChocolateText"
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#af196f">+0</TextBlock>
<TextBlock
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#af196f">°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<Border
Width="100"
Height="63"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="7">
<TextBlock
FontSize="15"
HorizontalAlignment="Center"
Foreground="#666666">REAL TEMP.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock
x:Name="ChocolateRealTemp"
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#000000">0</TextBlock>
<TextBlock
FontSize="23.5"
HorizontalAlignment="Center"
Foreground="#000000">°C</TextBlock>
</StackPanel>
</StackPanel>
</Border>
<StackPanel Spacing="3">
<Border Width="70"
Height="30"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="9">
<TextBlock FontSize="15"
HorizontalAlignment="Center"
Foreground="#231f20">AUTO</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="60" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
<Border Width="70"
Height="30"
Background="#e6e6e6"
CornerRadius="5"
Padding="5">
<StackPanel Spacing="9">
<TextBlock FontSize="15"
HorizontalAlignment="Center"
Foreground="#231f20">ON/OFF</TextBlock>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="60" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Border>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
<Border Width="150"
Height="90"
Background="#f9f9f9"
Grid.Row="1" CornerRadius="10"
Padding="5"
PointerPressed="ToggleMoldHeaterClick"
>
<StackPanel>
<TextBlock FontSize="15"
Foreground="#666666"
HorizontalAlignment="Center">MOLD HEATER</TextBlock>
<TextBlock x:Name="MoldHeaterStatus" FontSize="47"
Foreground="#231f20"
HorizontalAlignment="Center">OFF</TextBlock>
<!-- Underline -->
<Rectangle x:Name="MoldHeaterUnderline" Fill="#666666" Height="5" Width="110" Margin="0,-10,0,0"></Rectangle>
</StackPanel>
</Border>
<Border Width="150"
Height="90"
Background="#f9f9f9"
Grid.Row="2" CornerRadius="10"
Padding="5"
PointerPressed="ToggleVibrationClick"
>
<StackPanel>
<TextBlock FontSize="15"
Foreground="#666666"
HorizontalAlignment="Center">VIBRATION</TextBlock>
<TextBlock x:Name="VibrationStatus" FontSize="47"
Foreground="#231f20"
HorizontalAlignment="Center">OFF</TextBlock>
<!-- Underline -->
<Rectangle x:Name="VibrationUnderline" Fill="#666666" Height="5" Width="110" Margin="0,-10,0,0"></Rectangle>
</StackPanel>
</Border>
<Border Width="150"
Height="90"
Background="#f9f9f9"
Grid.Row="3" CornerRadius="10"
VerticalAlignment="Top"
Margin="0,-20,0,0"
Padding="5"
PointerPressed="ToggleVibHeaterClick"
>
<StackPanel>
<TextBlock FontSize="15"
Foreground="#666666"
HorizontalAlignment="Center">VIB. HEATER</TextBlock>
<TextBlock x:Name="VibHeaterStatus" FontSize="47"
Foreground="#231f20"
HorizontalAlignment="Center">OFF</TextBlock>
<!-- Underline -->
<Rectangle x:Name="VibHeaterUnderline" Fill="#666666" Height="5" Width="110" Margin="0,-10,0,0"></Rectangle>
</StackPanel>
</Border>
</Grid>
</Grid>
<!--number keyBoard-->
<Border x:Name="keyBoardPopup"
Background="#80000000"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="False"
ZIndex="50"
PointerPressed="OnPopupOverlayPointerPressed">
<Grid MaxWidth="500" MaxHeight="500" HorizontalAlignment="Center" VerticalAlignment="Center"
Margin="0,0,0,0"
PointerPressed="InnerPopupPointerPressed">
<Border x:Name="PopupControl"
BorderThickness="2"
CornerRadius="10"
Padding="10"
PointerPressed="InnerPopupPointerPressed">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="10">
<!-- Popup Content (Keypad etc.) -->
<Grid IsVisible="True">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="FontSize" Value="50"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="RenderTransform" Value="scale(1.11)"/>
</Style>
</Grid.Styles>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!-- Keypad Buttons -->
<Button Content="1" Grid.Row="0" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="2" Grid.Row="0" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="3" Grid.Row="0" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="4" Grid.Row="1" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="5" Grid.Row="1" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="6" Grid.Row="1" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="7" Grid.Row="2" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="8" Grid.Row="2" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="9" Grid.Row="2" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="BACK" Grid.Row="3" Grid.Column="0" FontSize="20" Background="#D3D3D3" Margin="5" Click="OnBackClick"/>
<Button Content="0" Grid.Row="3" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button x:Name="enterBtn" Content="ENTER" Grid.Row="3" Grid.Column="2" FontSize="20" Background="#A4275D" Foreground="White" Margin="5" Click="EnterClick"/>
<Button Content="-" Grid.Row="3" Grid.Column="3" FontSize="50" Background="White" Foreground="Black"
Margin="5" Click="OnKeyClick"/>
<Button Content="+" Grid.Row="2" Grid.Column="3" FontSize="50" Background="White" Foreground="Black"
Margin="5" Click="OnKeyClick"/>
<Button Content="." Grid.Row="1" Grid.Column="3" FontSize="50" Background="White" Foreground="Black"
Margin="5" Click="OnKeyClick"/>
</Grid>
</Grid>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/ManualControl.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using DaireApplication.DataBase;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.Reflection.PortableExecutable;
namespace DaireApplication;
public partial class ManualControl : UserControl
{
private MainWindow? _mainWindow;
bool isNegative = false;
TextBlock targetText = new TextBlock();
float oldValue = 0;
public MachineTable _machine { get; set; }
public ManualControl()
{
InitializeComponent();
}
public ManualControl(MainWindow mainWindow)
{
_mainWindow = mainWindow;
_machine = new MachineTable();
InitializeComponent();
setDefaultSettings();
getUiElementes();
}
private void setDefaultSettings()
{
_mainWindow.minimizeBtn.IsVisible = false;
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
//_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = true;
_mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
_mainWindow.SoftwareTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.TitleBtn.IsVisible = false;
_mainWindow.ManualControlTrack.IsVisible = true;
_mainWindow.ManualControlPolygon.Stroke = Brush.Parse("#A4275D");
//_mainWindow.Title.Text = _recipeTable.Name;
//Set Footer
_mainWindow.footerMsg.IsVisible = false;
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = true;
_mainWindow.version.IsVisible = false;
_mainWindow.chefBtns.IsVisible = false;
}
private void ToggleMoldHeaterClick(object? sender, PointerPressedEventArgs e)
{
if (MoldHeaterStatus.Text == "ON")
{
_mainWindow.moldHeaterMotor = 0;
//MoldHeaterStatus.Text = "OFF";
//MoldHeaterUnderline.Fill = Brush.Parse("#666666");
}
else
{
_mainWindow.moldHeaterMotor = 1;
//MoldHeaterStatus.Text = "ON";
//MoldHeaterUnderline.Fill = Brush.Parse("#A4275D");
}
}
private void ToggleVibrationClick(object? sender, PointerPressedEventArgs e)
{
if (VibrationStatus.Text == "ON")
{
_mainWindow.vibrationMotor = 0;
//VibrationStatus.Text = "OFF";
//VibrationUnderline.Fill = Brush.Parse("#666666");
}
else
{
_mainWindow.vibrationMotor = 1;
//VibrationStatus.Text = "ON";
//VibrationUnderline.Fill = Brush.Parse("#A4275D");
}
}
private void ToggleVibHeaterClick(object? sender, PointerPressedEventArgs e)
{
if (VibHeaterStatus.Text == "ON")
{
_mainWindow.vibHeaterMotor = 0;
//VibHeaterStatus.Text = "OFF";
//VibHeaterUnderline.Fill = Brush.Parse("#666666");
}
else
{
_mainWindow.vibHeaterMotor = 1;
//VibHeaterStatus.Text = "ON";
//VibHeaterUnderline.Fill = Brush.Parse("#A4275D");
}
}
private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e)
{
if (isNegative)
{
targetText.Text = "-" + oldValue.ToString("0.0");
}
else
{
targetText.Text = "+" + oldValue.ToString("0.0");
}
keyBoardPopup.IsVisible = false;
}
private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e)
{
e.Handled = true;
}
private void OnKeyClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if ((button.Content == "+" || button.Content == "-") && targetText.Text.Length > 0)
{
}
else if ((targetText.Text.Length == 0 && button.Content == ".") || (targetText.Text.Contains(".") && button.Content == "."))
{
}
else
{
targetText.Text += button.Content;
}
}
}
private void OnBackClick(object? sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(targetText.Text))
{
// Remove the last character from the text box
targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1);
//number = number.Remove(number.Length - 1);
}
}
private async void EnterClick(object? sender, RoutedEventArgs e)
{
var tankBtm = _mainWindow._mapping.Find(x => x.Name.ToLower() == "Tank Bottom Temp".ToLower());
var pumb = _mainWindow._mapping.Find(x => x.Name.ToLower() == "Pump Temp".ToLower());
var fount = _mainWindow._mapping.Find(x => x.Name.ToLower() == "Fountain Temp".ToLower());
List<int> setTempValues = new List<int>();
setTempValues.AddRange([_mainWindow.holdingRegister.setTemp1, _mainWindow.holdingRegister.setTemp2, _mainWindow.holdingRegister.setTemp3, _mainWindow.holdingRegister.setTemp4]);
if (sender is Button button)
{
if (!string.IsNullOrEmpty(targetText.Text))
{
float number = float.Parse(targetText.Text);
if (char.IsDigit(targetText.Text[0]))
{
targetText.Text = "+" + number.ToString("0.0");
}
else
{
targetText.Text = number.ToString("0.0");
}
var machine = _machine.ReadMachine();
if (button.Tag.ToString() == "t1")
{
foreach (var item in tankBtm.BitNumbers)
{
setTempValues[item - 8] = (int)(number * 10);
}
machine.setTemp1 = number;
}
else if (button.Tag.ToString() == "t3")
{
foreach (var item in pumb.BitNumbers)
{
setTempValues[item - 8] = (int)(number * 10);
}
machine.setTemp3 = number;
}
else if (button.Tag.ToString() == "t4")
{
foreach (var item in fount.BitNumbers)
{
setTempValues[item - 8] = (int)(number * 10);
}
machine.setTemp4 = number;
}
_mainWindow.holdingRegister.setTemp1 = setTempValues[0];
_mainWindow.holdingRegister.setTemp2 = setTempValues[1];
_mainWindow.holdingRegister.setTemp3 = setTempValues[2];
_mainWindow.holdingRegister.setTemp4 = setTempValues[3];
_machine.UpdateMachine(machine);
getUiElementes();
keyBoardPopup.IsVisible = false;
await _mainWindow.WriteToSerialAsync("DiagnosticsEnter");
}
}
}
private void ShowNumberKeyBoard(object? sender, PointerPressedEventArgs e)
{
if (sender is Border border)
{
//var parent = border.Parent as StackPanel;
//var brother = parent.Children[0] as Border;
//targetButton = brother.Child as Button;
if (border.Tag?.ToString() == "t1")
{
targetText = setTankBtmText;
}
else if (border.Tag?.ToString() == "t3")
{
targetText = setHelixText;
}
else if (border.Tag?.ToString() == "t4")
{
targetText = setChocolateText;
}
enterBtn.Tag = border.Tag;
isNegative = targetText.Text.StartsWith("-");
var x = targetText.Text.Substring(1);
oldValue = float.Parse(x);
targetText.Text = "";
keyBoardPopup.IsVisible = true;
}
}
private void getUiElementes()
{
var machine = _machine.ReadMachine();
setTankBtmText.Text = char.IsDigit(machine.setTemp1.ToString()[0]) ? "+" + machine.setTemp1.ToString() : machine.setTemp1.ToString("0.0");
setHelixText.Text = char.IsDigit(machine.setTemp3.ToString()[0]) ? "+" + machine.setTemp3.ToString() : machine.setTemp3.ToString("0.0");
setChocolateText.Text = char.IsDigit(machine.setTemp4.ToString()[0]) ? "+" + machine.setTemp4.ToString() : machine.setTemp4.ToString("0.0");
}
}
============================================================
FILE: DaireApplication/Views/UserController/Recipe.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="1200"
x:Class="DaireApplication.Recipe">
<Grid RowDefinitions="*">
<!-- Main Area-->
<Grid Grid.Row="0" ColumnDefinitions="Auto,1.5*" >
<Grid Grid.Column="1" >
<Grid x:Name="machinePic" Height="698" Width="465" >
<Grid.Background >
<ImageBrush Source="/Assets/Machine.png" Stretch="UniformToFill"/>
</Grid.Background>
</Grid>
</Grid>
<Grid Grid.Column="0" RowDefinitions="Auto,*">
<StackPanel Margin="10,50,0,10" Grid.Row="0" HorizontalAlignment="Center" >
<Label Foreground="#333333" FontSize="40" FontWeight="Normal" x:Name="RecipeTitle">Recipe SELECTION</Label>
</StackPanel>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Margin="0,0">
<Grid x:Name="DynamicGrid">
<!-- Define three columns -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"></Setter>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="RenderTransform" Value="scale(1.11)"></Setter>
<Setter Property="Background" Value="White"></Setter>
</Style>
</Grid.Styles>
<!-- Dynamic rows will be generated programmatically in code-behind -->
</Grid>
</ScrollViewer>
</Grid>
</Grid>
<!-- Overlay Background for Add Popup -->
<Border x:Name="PopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid x:Name="NameModule" PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="foucs" Text="Enter Recipe Name:"
FontSize="18"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
<Border x:Name="nameBorder">
<TextBox x:Name="NameInput"
Width="300"
Height="30"
BorderBrush="#CCC"
BorderThickness="1"
MaxLength="9"
></TextBox>
</Border>
<!-- Local styles for this specific TextBox -->
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
<!-- Save Button -->
<Button x:Name="SaveButton"
Content="Save"
FontSize="16"
Padding="10,5"
Click="saveRecipeClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Effect>
</Button.Effect>
</Button>
<!-- Cancel Button -->
<Button x:Name="CancelButton"
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="OnPopupOverlayPointerPressed">
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="managePopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnDeletePopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="modify the action "
FontSize="20"
FontWeight="Bold"
Foreground="Red"
Margin="0,0,0,8"
HorizontalAlignment="Center"/>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<!-- update Button -->
<Button
Name="updateActionBtn"
Content="Update"
FontSize="16"
Padding="10,5"
Click="UpdateActionClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
</Button>
<!-- delete Button -->
<Button
Name="deleteActionBtn"
Content="Delete"
FontSize="16"
Padding="10,5"
Click="deleteActionClick"
Foreground="White"
Background="Red">
</Button>
<!-- No Button -->
<Button
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="OnDeletePopupOverlayPointerPressed">
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Add Popup -->
<Border x:Name="updatePopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnDeletePopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="Rename:"
FontSize="18"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
<Border x:Name="updateBorder">
<TextBox x:Name="updateInput"
Width="300"
Height="30"
BorderBrush="#CCC"
BorderThickness="1"
MaxLength="9"
>
<!-- Local styles for this specific TextBox -->
<TextBox.Styles>
<!-- Normal (unfocused) style -->
<Style Selector="TextBox">
<Setter Property="Background" Value="White" />
<Setter Property="Foreground" Value="Black" />
</Style>
</TextBox.Styles>
</TextBox>
</Border>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
<!-- Save Button -->
<Button x:Name="saveUpdateBtn"
Content="Save"
FontSize="16"
Padding="10,5"
Click="SaveUpdateClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
</Button>
<!-- Cancel Button -->
<Button x:Name="cancelBtn"
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="OnDeletePopupOverlayPointerPressed">
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="DeletePopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnDeletePopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="Delete Warning!!"
FontSize="20"
FontWeight="Bold"
Foreground="Red"
Margin="0,0,0,8" />
<StackPanel>
<TextBlock x:Name="deleteMsg" Text="Are you sure?"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<!-- yes Button -->
<Button
Content="Yes"
FontSize="16"
Padding="10,5"
Click="YesBtnClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Effect>
</Button.Effect>
</Button>
<!-- No Button -->
<Button
Content="No"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="OnDeletePopupOverlayPointerPressed">
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/Recipe.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Threading;
using AvaloniaApplication1.DataBase;
using DaireApplication.Views;
using ReactiveUI;
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
namespace DaireApplication;
public partial class Recipe : UserControl
{
Button recipeButton = new Button();
private bool _isLongPress;
private MainWindow? _mainWindow;
private UserTable? _currentUser;
private RecipeTable _recipeTable=new RecipeTable();
private Process? _keyboardProcess;
public Recipe()
{
InitializeComponent();
}
public Recipe(MainWindow mainWindow,UserTable currentUser)
{
_currentUser = currentUser;
_mainWindow = mainWindow;
InitializeComponent();
nameBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
updateBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
setDefaultSettings();
addDynamicButtons();
}
private async void OnRecipeClick(object? sender, RoutedEventArgs e)
{
if (_isLongPress)
{
// Reset the flag for future interactions.
_isLongPress = false;
// Ignore this click since a long press was detected.
return;
}
if (sender is Button button)
{
if (_currentUser.CanEdit)
{
_mainWindow.FindControl<ContentControl>("ContentArea").Content = new RecipeEdit(_mainWindow, _currentUser, _recipeTable.ReadRecipesById(button.Name));
}
else
{
_mainWindow.FindControl<ContentControl>("ContentArea").Content = new Settings(_mainWindow, _currentUser, _recipeTable.ReadRecipesById(button.Name));
_mainWindow.restBoard = true;
}
}
}
private async void deleteActionClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
deleteMsg.Text = $"You are about to delete {button.Tag}";
DeletePopupOverlay.IsVisible = true;
}
}
private async void UpdateActionClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var text = recipeButton.Content as TextBlock;
updateInput.Text = $"{text.Text}";
updatePopupOverlay.IsVisible = true;
}
}
private void OnLongRecipeClick(object? sender, RoutedEventArgs e)
{
if (e is HoldingRoutedEventArgs args)
{
if (args.HoldingState == HoldingState.Started)
{
_isLongPress = true;
if (sender is Button button)
{
var targetText= button.Content as TextBlock;
deleteActionBtn.Tag = targetText.Text;
managePopupOverlay.IsVisible = true;
recipeButton = button;
//recipeButton = button;
//if (button.Content is TextBlock targetText)
//{
// deleteMsg.Text = $"You are about to delete {targetText.Text}";
//}
}
args.Handled = true;
}
else if (args.HoldingState == HoldingState.Completed)
{
_isLongPress = false;
}
}
}
private void CloseKeyboard()
{
try
{
if (_keyboardProcess != null)
{
// Kill the keyboard process
_keyboardProcess.Kill();
_keyboardProcess.Dispose();
_keyboardProcess = null;
// Force kill any remaining keyboard processes
var processKill = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "killall",
Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards
UseShellExecute = false,
CreateNoWindow = true
}
};
processKill.Start();
processKill.WaitForExit(1000);
processKill.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error closing keyboard: {ex.Message}");
}
}
public void AttachHandlers(Button button)
{
if (button != null)
{
button.Holding += OnLongRecipeClick;
button.PointerPressed += (sender, e) =>
{
// Simulate a long press on any pointer (mouse or touch)
var point = e.GetPosition(button);
OnLongRecipeClick(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type));
};
button.PointerReleased += (sender, e) =>
{
// End simulated long press
var point = e.GetPosition(button);
OnLongRecipeClick(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type));
};
}
}
private async void OnAddRecipeClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
PopupOverlay.IsVisible = true;
}
}
private async void OnPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
PopupOverlay.IsVisible = false;
}
private async void OnDeletePopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
DeletePopupOverlay.IsVisible = false;
managePopupOverlay.IsVisible = false;
updatePopupOverlay.IsVisible = false;
}
private async void YesBtnClick(object? sender, RoutedEventArgs e)
{
var result = _recipeTable.DeleteRecipe(recipeButton.Name);
if (result)
{
addDynamicButtons();
DeletePopupOverlay.IsVisible= false;
managePopupOverlay.IsVisible = false;
}
else
{
}
}
private async void SaveUpdateClick(object? sender, RoutedEventArgs e)
{
if (!_recipeTable.DoesNameExist(updateInput.Text))
{
var recipe = _recipeTable.ReadRecipesById(recipeButton.Name);
recipe.Name = updateInput.Text;
var result = _recipeTable.UpdateRecipe(recipe);
if (result)
{
addDynamicButtons();
managePopupOverlay.IsVisible = false;
updatePopupOverlay.IsVisible = false;
CloseKeyboard();
}
else
{
}
}
else
{
CloseKeyboard();
await MainWindow.MessageBox.Show(_mainWindow, "this name is already in use", "Error");
_mainWindow.Topmost = false;
_mainWindow.Focus();
_mainWindow.Activate();
}
}
private void showPopUp(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
recipeButton = button;
button.Foreground = Brush.Parse("#A4275D");
PopupOverlay.IsVisible = true;
// Append the button's content to the input box
//InputTextBox.Text += button.Content?.ToString();
}
}
private async void saveRecipeClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (!string.IsNullOrEmpty(NameInput.Text))
{
if (!_recipeTable.DoesNameExist(NameInput.Text))
{
RecipeTable data = new RecipeTable();
data.Name = NameInput.Text;
data.Mixer = false;
data.Fountain = false;
data.MoldHeater = false;
data.Vibration = false;
data.VibHeater = false;
data.Pedal = false;
var result = _recipeTable.AddRecipe(data);
if (result)
{
addDynamicButtons();
CloseKeyboard();
NameInput.Text = "";
PopupOverlay.IsVisible = false;
}
else
{
}
}
else
{
CloseKeyboard();
await MainWindow.MessageBox.Show(_mainWindow, "this name is already in use", "Error");
_mainWindow.Topmost = false;
_mainWindow.Activate();
}
}
}
}
private (string? fileName, string args) GetKeyboardCommand()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return ("osk.exe", "");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return ("onboard", ""); // or "florence", "matchbox-keyboard"
return (null, "");
}
private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e)
{
if (_keyboardProcess is { HasExited: false })
return;
var (fileName, args) = GetKeyboardCommand();
if (fileName is null)
return;
_keyboardProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = args,
UseShellExecute = true
},
EnableRaisingEvents = true
};
try
{
_keyboardProcess.Start();
Dispatcher.UIThread.Post(() =>
{
if (sender is Border border)
{
var textbox= border.Child as TextBox;
textbox.SelectionStart = 0;
textbox.SelectionEnd = textbox.Text?.Length ?? 0;
}
});
}
catch
{
// fail silently if keyboard not found
}
}
private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e)
{
// Close the popup when clicking outside of it
recipeButton.Foreground = Avalonia.Media.Brushes.Black;
PopupOverlay.IsVisible = false;
}
private void setDefaultSettings()
{
//set recipe title
if (_currentUser.CanEdit)
{
RecipeTitle.Content = "RECIPE EDIT/ADD PANEL";
}
else
{
RecipeTitle.Content = "RECIPE SELECTION";
}
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = false;
if (_currentUser.CanEdit)
{
_mainWindow.RecipePanelTrack.IsVisible = true;
_mainWindow.RecipePanelPolygon.Stroke = Brush.Parse("#A4275D");
}
else
{
_mainWindow.RecipeSelTrack.IsVisible = true;
_mainWindow.RecipeSelPolygon.Stroke = Brush.Parse("#A4275D");
}
//_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.TitleBtn.IsVisible = false;
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.SoftwareTrack.IsVisible = false;
//Set Footer
if (_currentUser.CanEdit)
{
_mainWindow.footerMsg.Text = "Long press to delete recipe";
_mainWindow.footerMsg.IsVisible = true;
_mainWindow.chefBtns.IsVisible = true;
}
else
{
_mainWindow.footerMsg.Text = "Select a recipe to start";
_mainWindow.footerMsg.IsVisible = true;
}
_mainWindow.ManualControlTrack.IsVisible = false;
_mainWindow.footerMsg.MaxWidth = 1000;
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D");
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = false;
}
private void addDynamicButtons()
{
var recipes= _recipeTable.ReadRecipes();
var grid = this.FindControl<Grid>("DynamicGrid");
grid.Children.Clear();
int lastRow = 0;
int lastCol = 0;
int colIndexForExtraData = 0;
int recipeIndex = 0;
try
{
if (recipes.Count<3)
{
// Add dynamic rows
for (int i = 0; i < (int)Math.Ceiling((double)recipes.Count / 3); i++) // Example: 20 rows
{
lastRow = i;
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// Add content for each column
for (int col = 0; col < recipes.Count; col++)
{
lastCol = col;
var text = new TextBlock
{
Padding = new Thickness(10),
Text = recipes[recipeIndex + col].Name,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
FontSize = 31,
FontWeight=FontWeight.Normal,
Foreground = Avalonia.Media.Brushes.Black
};
var button = new Button
{
Width = 210,
Height = 160,
Margin = new Thickness(3),
Content = text,
Name = recipes[recipeIndex + col].Id.ToString(),
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
};
button.Click += OnRecipeClick;
if (_currentUser.CanEdit)
{
//button.Holding += OnLongRecipeClick;
AttachHandlers(button);
//button.DoubleTapped += OnDoubleRecipeClick;
}
grid.Children.Add(button);
Grid.SetRow(button, i);
Grid.SetColumn(button, col);
}
recipeIndex += 3;
}
if (_currentUser.CanEdit)
{
var Plus = new TextBlock
{
Padding = new Thickness(10),
Text = "+",
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
FontSize = 100,
Foreground = Brush.Parse("#A4275D")
};
var AddButtun = new Button
{
Width = 210,
Height = 160,
Margin = new Thickness(3),
Content = Plus,
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center,
Padding = new Thickness(0, 0, 0, 15),
};
AddButtun.Click += OnAddRecipeClick;
if (lastCol < 2)
{
grid.Children.Add(AddButtun);
Grid.SetRow(AddButtun, lastRow);
Grid.SetColumn(AddButtun, lastCol + 1);
}
else
{
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.Children.Add(AddButtun);
Grid.SetRow(AddButtun, lastRow + 1);
Grid.SetColumn(AddButtun, 0);
}
}
}
else
{
// Add dynamic rows
for (int i = 0; i < (int)Math.Floor((double)recipes.Count / 3); i++) // Example: 20 rows
{
lastRow = i;
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
// Add content for each column
for (int col = 0; col < 3; col++)
{
lastCol = col;
var text = new TextBlock
{
Padding = new Thickness(10),
Text = recipes[recipeIndex + col].Name,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
FontSize = 31,
FontWeight = FontWeight.Normal,
Foreground = Avalonia.Media.Brushes.Black
};
var button = new Button
{
Width = 210,
Height = 160,
Margin = new Thickness(3),
Content = text,
Name = recipes[recipeIndex + col].Id.ToString(),
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
};
button.Click += OnRecipeClick;
if (_currentUser.CanEdit)
{
//button.Holding += OnLongRecipeClick;
AttachHandlers(button);
//button.DoubleTapped += OnDoubleRecipeClick;
}
grid.Children.Add(button);
Grid.SetRow(button, i);
Grid.SetColumn(button, col);
}
recipeIndex += 3;
}
for (int i = 0; i < recipes.Count -recipeIndex; i++)
{
var text = new TextBlock
{
Padding = new Thickness(10),
Text = recipes[recipeIndex + i].Name,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
FontSize = 31,
FontWeight = FontWeight.Normal,
Foreground = Avalonia.Media.Brushes.Black
};
var button = new Button
{
Width = 210,
Height = 160,
Margin = new Thickness(3),
Content = text,
Name = recipes[recipeIndex + i].Id.ToString(),
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
};
button.Click += OnRecipeClick;
if (_currentUser.CanEdit)
{
//button.Holding += OnLongRecipeClick;
AttachHandlers(button);
//button.DoubleTapped += OnDoubleRecipeClick;
}
if (lastCol < 2)
{
lastCol += 1;
grid.Children.Add(button);
Grid.SetRow(button,lastRow);
Grid.SetColumn(button, lastCol);
}
else
{
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.Children.Add(button);
Grid.SetRow(button, lastRow + 1);
Grid.SetColumn(button, colIndexForExtraData);
colIndexForExtraData += 1;
}
}
if (_currentUser.CanEdit)
{
var Plus = new TextBlock
{
Padding = new Thickness(10),
Text = "+",
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
FontSize = 100,
Foreground = Brush.Parse("#A4275D"),
};
var AddButtun = new Button
{
Width = 210,
Height = 160,
Margin = new Thickness(3),
Content = Plus,
CornerRadius = new CornerRadius(10),
Background = Avalonia.Media.Brushes.White,
VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center,
HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center,
HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center,
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center,
Padding = new Thickness(0,0,0,15),
};
AddButtun.Click += OnAddRecipeClick;
if (lastCol < 2)
{
grid.Children.Add(AddButtun);
Grid.SetRow(AddButtun, lastRow);
Grid.SetColumn(AddButtun, lastCol + 1);
}
else
{
grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
grid.Children.Add(AddButtun);
Grid.SetRow(AddButtun, lastRow + 1);
Grid.SetColumn(AddButtun, colIndexForExtraData);
}
}
}
}
catch (Exception)
{
}
}
}
============================================================
FILE: DaireApplication/Views/UserController/RecipeEdit.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="DaireApplication.RecipeEdit"
Width="1200"
mc:Ignorable="d" >
<Grid>
<!-- Main Content (machine picture on left, etc.) -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- Machine Picture on Left -->
<Grid Grid.Column="0">
<Grid x:Name="machinePic" IsVisible="True" Width="937" Height="567">
<Grid.Background>
<ImageBrush Source="/Assets/TemperingGraphics.png"/>
</Grid.Background>
</Grid>
</Grid>
<!-- (Optional additional content on right if needed) -->
</Grid>
<!-- Popup Overlay -->
<Border x:Name="PopupOverlay"
Background="#80000000"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="False"
ZIndex="50"
PointerPressed="OnPopupOverlayPointerPressed">
<Grid MaxWidth="500" MaxHeight="500" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border x:Name="PopupControl"
BorderThickness="2"
CornerRadius="10"
Padding="10"
PointerPressed="OnPopupOverlayPointerPressed">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="10">
<!-- Popup Content (Keypad etc.) -->
<Grid IsVisible="True">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="FontSize" Value="50"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="RenderTransform" Value="scale(1.11)"/>
</Style>
</Grid.Styles>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!-- Keypad Buttons -->
<Button Content="1" Grid.Row="0" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="2" Grid.Row="0" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="3" Grid.Row="0" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="4" Grid.Row="1" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="5" Grid.Row="1" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="6" Grid.Row="1" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="7" Grid.Row="2" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="8" Grid.Row="2" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="9" Grid.Row="2" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="BACK" Grid.Row="3" Grid.Column="0" FontSize="20" Background="#D3D3D3" Margin="5" Click="OnBackClick"/>
<Button Content="0" Grid.Row="3" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="ENTER" Grid.Row="3" Grid.Column="2" FontSize="20" Background="#A4275D" Foreground="White" Margin="5" Click="EnterClick"/>
</Grid>
</Grid>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Container for the Three Buttons (always at the right side) -->
<StackPanel x:Name="ButtonOverlayContainer"
Orientation="Vertical"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="0,0,20,20"
Spacing="20"
ZIndex="100"
>
<Border CornerRadius="10"
Background="White"
Padding="20"
Margin="20"
Width="270"
Height="400" ZIndex="49" >
<!-- Use a Grid with RowDefinitions to position elements -->
<Grid ZIndex="49">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<!-- First button -->
<RowDefinition Height="9*" />
<!-- Spacer to push content to bottom -->
<RowDefinition Height="Auto" />
<!-- Second button -->
<RowDefinition Height="3*" />
<!-- Spacer to push content to bottom -->
<RowDefinition Height="Auto" />
<!-- Third button -->
<RowDefinition Height="7*" />
<!-- Spacer to push content to bottom -->
<RowDefinition Height="Auto" />
<!-- Arrow + label at bottom -->
</Grid.RowDefinitions>
<Grid.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Background" Value="LightGray"></Setter>
</Style>
</Grid.Styles>
<Grid.Styles>
<Style Selector="Button:disabled /template/ContentPresenter" >
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Grid.Styles>
<!-- Red Button for Heating -->
<Button Grid.Row="0" x:Name="heatingBtn"
Background="#FFFF5252"
Foreground="White"
FontSize="25"
Padding="10,5"
BorderThickness="0"
Width="230"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
CornerRadius="10"
Click="showPopUp"
>
<StackPanel Spacing="5" Orientation="Horizontal">
<TextBlock>HEATING: </TextBlock>
<TextBlock x:Name="heatingValue"></TextBlock>
<TextBlock> °C</TextBlock>
</StackPanel>
</Button>
<TextBlock Grid.Row="1" TextWrapping="WrapWithOverflow" VerticalAlignment="Center" FontWeight="Normal" FontSize="14" Foreground="Red" x:Name="tempErrorMsg">
</TextBlock>
<!-- Brown Button for Pouring -->
<Button Grid.Row="2" x:Name="pouringBtn"
Background="#FF795548"
Foreground="White"
FontSize="25"
Padding="10,5"
BorderThickness="0"
Width="230"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center"
CornerRadius="10"
Click="showPopUp" >
<StackPanel Spacing="5" Orientation="Horizontal">
<TextBlock>POURING: </TextBlock>
<TextBlock x:Name="pouringValue"></TextBlock>
<TextBlock> °C</TextBlock>
</StackPanel>
</Button>
<!-- Blue Button for Cooling -->
<Button Grid.Row="4" x:Name="coolingBtn"
Classes="NotEnabled"
FontSize="25"
Background="#FF448AFF"
Foreground="White"
Padding="10,5"
BorderThickness="0"
Width="230"
HorizontalAlignment="Center"
CornerRadius="10"
HorizontalContentAlignment="Center"
Click="showPopUp" >
<StackPanel Spacing="5" Orientation="Horizontal">
<TextBlock>COOLING: </TextBlock>
<TextBlock x:Name="coolingValue"></TextBlock>
<TextBlock> °C</TextBlock>
</StackPanel>
</Button>
<!-- Arrow and 'EDIT HERE' Label at the Bottom -->
<StackPanel Grid.Row="6" HorizontalAlignment="Center">
<TextBlock Text="↑"
FontSize="50"
FontWeight="Normal"
HorizontalAlignment="Center"
Foreground="Black"/>
<TextBlock Text="EDIT HERE"
FontSize="30"
FontWeight="Normal"
HorizontalAlignment="Center"
Foreground="Black"
/>
</StackPanel>
</Grid>
</Border>
</StackPanel>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/RecipeEdit.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using AvaloniaApplication1.DataBase;
using DaireApplication.Views;
using System;
namespace DaireApplication;
public partial class RecipeEdit : UserControl
{
Button controllButton = new Button();
private MainWindow? _mainWindow;
private UserTable? _currentUser;
private RecipeTable? _recipeTable;
public RecipeEdit()
{
InitializeComponent();
}
public RecipeEdit(MainWindow mainWindow, UserTable currentUser,RecipeTable recipeTable)
{
_currentUser = currentUser;
_mainWindow = mainWindow;
_recipeTable=recipeTable;
InitializeComponent();
setDefaultSettings();
}
string oldNumber = "";
private void OnKeyClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var StackPanel = controllButton.Content as StackPanel;
var Label = StackPanel.Children;
if (Label[1] is TextBlock targetText)
{
//number += button.Content?.ToString();
targetText.Text += button.Content ;
}
// Append the button's content to the input box
//InputTextBox.Text += button.Content?.ToString();
}
}
private void OnBackClick(object? sender, RoutedEventArgs e)
{
var StackPanel = controllButton.Content as StackPanel;
var Label = StackPanel.Children;
if (Label[1] is TextBlock targetText)
{
if (!string.IsNullOrEmpty(targetText.Text))
{
// Remove the last character from the text box
targetText.Text = targetText.Text.Remove(targetText.Text.Length -1, 1);
//number = number.Remove(number.Length - 1);
}
}
}
private void EnterClick(object? sender, RoutedEventArgs e)
{
RecipeTable recipe = new RecipeTable();
recipe.Id = _recipeTable.Id;
recipe.Mixer = null;
recipe.Fountain = null;
recipe.MoldHeater = null;
recipe.Vibration = null;
recipe.VibHeater = null;
recipe.Pedal = null;
//getting the btn value
var heatingStackPanel = heatingBtn.Content as StackPanel;
var heatingLabel = heatingStackPanel.Children;
var heatingText = heatingLabel[1] as TextBlock;
var coolingStackPanel = coolingBtn.Content as StackPanel;
var coolingLabel = coolingStackPanel.Children;
var coolingText = coolingLabel[1] as TextBlock;
var StackPanel = controllButton.Content as StackPanel;
var Label = StackPanel.Children;
var targetText = Label[1] as TextBlock;
var activeTxt= Label[0] as TextBlock;
switch (activeTxt.Text)
{
case "HEATING:":
if (!string.IsNullOrEmpty(targetText.Text))
{
int value = Int32.Parse(targetText.Text);
if (value>60)
{
tempErrorMsg.Text = "Heating Tempreature must be lower than 60 <20>C";
return;
}
else if (value<40)
{
tempErrorMsg.Text = "Heating Tempreature must be greater than 40 <20>C";
return;
}
else
{
recipe.CoolingGoal = 0;
recipe.PouringGoal = 0;
recipe.HeatingGoal = value;
_recipeTable.UpdateRecipe(recipe);
tempErrorMsg.Text = "";
heatingBtn.IsEnabled = true;
coolingBtn.IsEnabled = true;
pouringBtn.IsEnabled = true;
PopupOverlay.IsVisible = false;
setDefaultSettings();
}
}
break;
case "POURING:":
if (!string.IsNullOrEmpty(targetText.Text))
{
int value = Int32.Parse(targetText.Text);
if (string.IsNullOrEmpty(heatingText.Text)||string.IsNullOrEmpty(coolingText.Text))
{
tempErrorMsg.Text = $"Enter heating and cooling tempreature first";
return;
}
if (value > Int32.Parse(heatingText.Text))
{
tempErrorMsg.Text = $"Pouring Tempreature must be lower than Heating Tempreatur({heatingText.Text}<7D>C)";
return;
}
else if (value < Int32.Parse(coolingText.Text))
{
tempErrorMsg.Text = $"Pouring Tempreature must be greater than Cooling Tempreatur({coolingText.Text}<7D>C)";
return;
}
else
{
recipe.HeatingGoal = 0;
recipe.CoolingGoal = 0;
recipe.PouringGoal = value;
_recipeTable.UpdateRecipe(recipe);
tempErrorMsg.Text = "";
heatingBtn.IsEnabled = true;
coolingBtn.IsEnabled = true;
pouringBtn.IsEnabled = true;
PopupOverlay.IsVisible = false;
setDefaultSettings();
}
}
break;
case "COOLING:":
if (!string.IsNullOrEmpty(targetText.Text))
{
int value = Int32.Parse(targetText.Text);
if (value > 40)
{
tempErrorMsg.Text = "Cooling Tempreature must be lower than 40 <20>C";
return;
}
else if (value < 20)
{
tempErrorMsg.Text = "Cooling Tempreature must be greater than 20 <20>C";
return;
}
else
{
recipe.HeatingGoal = 0;
recipe.PouringGoal = 0;
recipe.CoolingGoal = value;
_recipeTable.UpdateRecipe(recipe);
tempErrorMsg.Text = "";
heatingBtn.IsEnabled = true;
coolingBtn.IsEnabled = true;
pouringBtn.IsEnabled = true;
PopupOverlay.IsVisible = false;
setDefaultSettings();
}
}
break;
}
}
private void showPopUp(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
heatingBtn.IsEnabled = false;
coolingBtn.IsEnabled = false;
pouringBtn.IsEnabled = false;
button.IsEnabled = true;
var StackPanel = button.Content as StackPanel;
var Label = StackPanel.Children;
if (Label[1] is TextBlock targetText)
{
oldNumber = targetText.Text;
}
controllButton = button;
PopupOverlay.IsVisible = true;
}
}
private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e)
{
// Close the popup when clicking outside of it
//controllButton.Foreground = Avalonia.Media.Brushes.Black;
var StackPanel = controllButton.Content as StackPanel;
var Label = StackPanel.Children;
if (Label[1] is TextBlock targetText)
{
//number += button.Content?.ToString();
targetText.Text = oldNumber;
}
tempErrorMsg.Text = "";
heatingBtn.IsEnabled = true;
coolingBtn.IsEnabled = true;
pouringBtn.IsEnabled = true;
PopupOverlay.IsVisible = false;
}
private void setDefaultSettings()
{
//set Values
_recipeTable = _recipeTable.ReadRecipesById(_recipeTable.Id.ToString());
heatingValue.Text = _recipeTable?.HeatingGoal == 0 ? "" : _recipeTable?.HeatingGoal.ToString();
coolingValue.Text = _recipeTable?.CoolingGoal == 0 ? "" : _recipeTable?.CoolingGoal.ToString();
pouringValue.Text = _recipeTable?.PouringGoal == 0 ? "" : _recipeTable?.PouringGoal.ToString();
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
//_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipePanelTrack.IsVisible = true;
_mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeEditTrack.IsVisible = true;
_mainWindow.RecipeEditPolygon.Stroke = Brush.Parse("#A4275D");
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.TitleBtn.IsVisible = true;
_mainWindow.Title.Text = _recipeTable.Name;
//Set Footer
_mainWindow.footerMsg.Text = "Select the tempereture to edit it";
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D");
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = false;
}
}
============================================================
FILE: DaireApplication/Views/UserController/Settings.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="1200"
Height="620"
Background="#b3b3b3"
x:Class="DaireApplication.Settings" FontFamily="Helvetica" >
<Grid RowDefinitions="*">
<!-- Main Area-->
<Grid Grid.Row="0">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="#F9F9F9"></Setter>
<Setter Property="CornerRadius" Value="50"></Setter>
<Setter Property="Width" Value="150"></Setter>
<Setter Property="Height" Value="90"></Setter>
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#F9F9F9"></Setter>
</Style>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter" >
<Setter Property="Background" Value="#E6E6E6"/>
<Setter Property="CornerRadius" Value="25"/>
</Style>
</Grid.Styles>
<Grid ColumnDefinitions="2*,1.4*,2.2*" >
<Grid Grid.Column="0" RowDefinitions="*,Auto,*,*" >
<Grid Grid.Row="1" Margin="5,0,0,0">
<StackPanel>
<TextBlock FontSize="18" TextWrapping="WrapWithOverflow" x:Name="mixerDelayTxt"
IsVisible="False"
Foreground="Black">Mixer
Delay: </TextBlock>
<TextBlock FontSize="25"
Margin="50,0,0,0"
x:Name="mixerDelayCounter"
IsVisible="False"
TextWrapping="WrapWithOverflow"
Foreground="Black">120</TextBlock>
</StackPanel>
</Grid>
<Grid Grid.Row="3" Margin="5,40,0,0">
<StackPanel>
<TextBlock FontSize="18" TextWrapping="WrapWithOverflow" x:Name="pedalDelayTxt"
IsVisible="False"
Foreground="Black">
Pedal OFF:
</TextBlock>
<TextBlock FontSize="25"
Margin="50,0,0,0"
x:Name="pedalDelayCounter"
IsVisible="False"
TextWrapping="WrapWithOverflow"
Foreground="Black">120</TextBlock>
</StackPanel>
</Grid>
</Grid>
<Grid Grid.Column="2"
RowDefinitions="*,Auto,*,*" ZIndex="200"
Margin="0,0,0,0" >
<Grid Grid.Row="1" Margin="305,0,0,0" ZIndex="200">
<StackPanel>
<TextBlock FontSize="18" TextWrapping="" x:Name="fountainDelayTxt"
IsVisible="False"
Foreground="Black">Fountain Delay: </TextBlock>
<TextBlock FontSize="25"
Margin="50,0,0,0"
IsVisible="False"
Foreground="Black"
x:Name="fountainDelayCounter"
TextWrapping="WrapWithOverflow">120</TextBlock>
<TextBlock FontSize="18" TextWrapping="" x:Name="fountainTargetTxt"
IsVisible="False"
Foreground="Black">Target Temp: </TextBlock>
<TextBlock FontSize="25"
Margin="50,0,0,0"
IsVisible="False"
Foreground="Black"
x:Name="fountainTagetTemp"
TextWrapping="WrapWithOverflow">120</TextBlock>
</StackPanel>
</Grid>
</Grid>
<Grid HorizontalAlignment="Center" Grid.Column="0" VerticalAlignment="Center" RowDefinitions="*,7*" Margin="40,0,0,20" ZIndex="100">
<StackPanel Grid.Row="1" Orientation="Vertical" >
<!--Tank Temp -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<Button IsEnabled="False" Margin="10" CornerRadius="10" >
<Button.Styles>
<!-- Custom Style for Disabled Button -->
<Style Selector="Button:disabled /template/ContentPresenter">
<Setter Property="Background" Value="#E6E6E6"/>
<Setter Property="Foreground" Value="#231F20"/>
</Style>
</Button.Styles>
<StackPanel Width="150" Height="90" Spacing="5">
<Label CornerRadius="25" FontSize="15.5"
FontWeight="Normal" Foreground="#8D8D8D" HorizontalContentAlignment="Center"
Margin="0,5,0,-5">TANK TEMP</Label>
<StackPanel
Spacing="-10"
Orientation="Horizontal"
Margin="0,-5,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Label x:Name="TankTempValue" FontSize="35" FontWeight="Normal"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center">-100.0</Label>
<Label FontSize="40" FontWeight="Normal" >°C</Label>
</StackPanel>
</StackPanel>
</Button>
</StackPanel>
<!--Mixer -->
<StackPanel Orientation="Horizontal" >
<Button x:Name="mixerBtn" CornerRadius="10" Margin="10" >
<StackPanel x:Name="MixerSP">
<Label FontSize="15.5" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#666666">MIXER</Label>
<Label FontSize="47" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#ff231f20" Margin="0,-15,0,0">OFF</Label>
<!-- Underline -->
<Rectangle Fill="#666666" Height="5" Width="110" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Button>
</StackPanel>
<!--Recipe Setting -->
<StackPanel Orientation="Horizontal" x:Name="recipeSettings" >
<Button CornerRadius="10" Margin="10" Padding="0">
<StackPanel Spacing="-7">
<Label FontSize="15" HorizontalContentAlignment="Center" Foreground="#AF196F" Margin="0,0,0,1">RECIPE SETTINGS</Label>
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<Label Grid.Column="0" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">Heating:</Label>
<Label Grid.Column="1" x:Name="heatingValue" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">47.0</Label>
<Label Grid.Column="2" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">°C</Label>
</Grid>
</Grid>
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<Label Grid.Column="0" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">Pouring:</Label>
<Label Grid.Column="1" x:Name="pouringValue" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">47.0</Label>
<Label Grid.Column="2" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">°C</Label>
</Grid>
</Grid>
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<Label Grid.Column="0" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">Cooling:</Label>
<Label Grid.Column="1" x:Name="coolingValue" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">47.0</Label>
<Label Grid.Column="2" FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#000000">°C</Label>
</Grid>
</Grid>
<StackPanel Orientation="Horizontal">
</StackPanel>
</StackPanel>
</Button>
</StackPanel>
<StackPanel HorizontalAlignment="Center" Width="150" Height="200">
<!-- Pedal Container -->
<Button Background="#F9F9F9" CornerRadius="10" Width="150" Height="200" VerticalContentAlignment="Center" HorizontalContentAlignment="Center">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Height="200" Width="150">
<!-- Pedal Title -->
<TextBlock Margin="7" Text="PEDAL" FontSize="15" FontWeight="Normal"
VerticalAlignment="Top" HorizontalAlignment="Center" Foreground="#666666" />
<!-- Auto Mode Button -->
<Button Background="#E6E6E6" CornerRadius="5" HorizontalAlignment="Center" Padding="0" Width="130" Height="50" Click="PedalBtn">
<StackPanel Width="130" x:Name="PedalSP">
<TextBlock x:Name="pedalStateTxt" Text="AUTO" Foreground="#231F20" FontSize="26.5" FontWeight="Normal" HorizontalAlignment="Center"/>
<!-- Underline -->
<Rectangle x:Name="pedalUnderLine" Fill="#A4275D" Height="5" Width="90" Margin="0,-3,0,0"/>
</StackPanel>
</Button>
<StackPanel x:Name="PedalAutoContainer" >
<!-- Pedal Off Time -->
<StackPanel.Styles>
<Style Selector="Button:disabled /template/ContentPresenter">
<Setter Property="Background" Value="#B3B3B3"/>
<Setter Property="Foreground" Value="#A4275D"/>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#E6E6E6"></Setter>
<Setter Property="Foreground" Value="#A4275D"></Setter>
</Style>
</StackPanel.Styles>
<TextBlock Text="PEDAL OFF TIME" Foreground="Gray" FontSize="15" FontWeight="Normal" HorizontalAlignment="Center"/>
<Grid RowDefinitions="*" Margin="5,0">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<Button Classes="PedalOn" Grid.Column="0" Content="" Background="#E6E6E6" Foreground="#A4275D"
Width="35" Height="35" CornerRadius="18" FontSize="16"
Click="adjustPedalTime"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock x:Name="PedalOnTime" Text="4" FontSize="23.5" FontWeight="Normal" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="s" FontSize="23.5" FontWeight="Normal" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
<Button Classes="PedalOn" Grid.Column="2" Content="+" Background="#E6E6E6" Foreground="#A4275D"
Width="35" Height="35" CornerRadius="18" FontSize="16" Click="adjustPedalTime"/>
</Grid>
</Grid>
<!-- Pedal On Time -->
<TextBlock Text="PEDAL ON TIME" Foreground="Gray" FontSize="15" FontWeight="Normal" HorizontalAlignment="Center"/>
<Grid RowDefinitions="*" Margin="5,0">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
<Button Classes="PedalOff" Grid.Column="0" Content="" Background="#E6E6E6" Foreground="#A4275D"
Width="35" Height="35" CornerRadius="18" FontSize="16" Click="adjustPedalTime"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock x:Name="PedalOffTime" Text="4" FontSize="23.5" FontWeight="Normal" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text=" s" FontSize="23.5" FontWeight="Normal" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
<Button Classes="PedalOff" Grid.Column="2" Content="+" Background="#E6E6E6" Foreground="#A4275D"
Width="35" Height="35" CornerRadius="18" FontSize="16" Click="adjustPedalTime"/>
</Grid>
</Grid>
</StackPanel>
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</Grid>
<Grid Grid.Column="1" Height="596" Width="605" IsVisible="True">
<Grid.Background >
<ImageBrush Source="/Assets/TemperingMachine.png" />
</Grid.Background>
</Grid>
<Grid Grid.Column="2" RowDefinitions="*,12*" HorizontalAlignment="Center" Margin="0,0,15,0">
<StackPanel Grid.Row="1" Orientation="Vertical" HorizontalAlignment="Left" >
<!--Fountain Temp -->
<StackPanel Orientation="Horizontal" >
<Button IsEnabled="False" Width="150" Height="90" Margin="10" CornerRadius="10" Padding="0">
<Button.Styles>
<!-- Custom Style for Disabled Button -->
<Style Selector="Button:disabled /template/ContentPresenter">
<Setter Property="Background" Value="#E6E6E6"/>
</Style>
</Button.Styles>
<StackPanel Spacing="5">
<Label FontSize="14.5" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#787878" >CHOCOLATE TEMP</Label>
<StackPanel
Spacing="-10"
Orientation="Horizontal"
Margin="0,-10,0,0" HorizontalAlignment="Center"
VerticalAlignment="Center">
<Label x:Name="FountainTempValue" FontSize="35" Foreground="#262223" VerticalAlignment="Center" >-100.0</Label>
<Label FontSize="40" Foreground="#262223" VerticalAlignment="Center" >°C</Label>
</StackPanel>
</StackPanel>
</Button>
</StackPanel>
<Button x:Name="fountainBtn" Margin="10" Content="on" Width="150" Height="90" CornerRadius="10">
<StackPanel x:Name="FountainSP">
<Label FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#666666">CHOCOLATE</Label>
<Label FontSize="47" FontWeight="Normal" HorizontalContentAlignment="Center" Margin="0,-15,0,0" Foreground="#231F20">ON</Label>
<!-- Underline -->
<Rectangle Fill="#A4275D" Height="5" Width="110" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Button>
<!--MOLD HEATER-->
<Button x:Name="moldHeaterBtn" Margin="10" Content="on" Width="150" Height="90" CornerRadius="10"
Click="toggelOnOffClick">
<StackPanel x:Name="MoldHeaterSP">
<Label FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#666666">MOLD HEATER</Label>
<Label FontSize="47" FontWeight="Normal" HorizontalContentAlignment="Center" Margin="0,-15,0,0" Foreground="#231F20">ON</Label>
<!-- Underline -->
<Rectangle Fill="#A4275D" Height="5" Width="110" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Button>
<!--Vibration-->
<Button x:Name="vibrationBtn" Margin="10" Content="on" Width="150" Height="90" CornerRadius="10"
Click="toggelOnOffClick">
<StackPanel x:Name="VibrationSP">
<Label FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#666666">VIBRATION</Label>
<Label FontSize="47" FontWeight="Normal" HorizontalContentAlignment="Center" Margin="0,-15,0,0" Foreground="#231F20">ON</Label>
<!-- Underline -->
<Rectangle Fill="#A4275D" Height="5" Width="110" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Button>
<!--VIBHeater-->
<Button x:Name="vibHeaterBtn" Margin="10" Content="on" Width="150" Height="90" CornerRadius="10"
Click="toggelOnOffClick">
<StackPanel x:Name="VibHeaterSP">
<Label FontSize="15" FontWeight="Normal" HorizontalContentAlignment="Center" Foreground="#666666"
>VIB. HEATER</Label>
<Label FontSize="47" FontWeight="Normal" HorizontalContentAlignment="Center" Margin="0,-15,0,0" Foreground="#231F20">ON</Label>
<!-- Underline -->
<Rectangle Fill="#A4275D" Height="5" Width="110" Margin="0,-15,0,0"></Rectangle>
</StackPanel>
</Button>
</StackPanel>
</Grid>
</Grid>
</Grid>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="DeletePopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnIgnorePopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="Exit Warning!!"
FontSize="20"
FontWeight="Bold"
Foreground="Red"
Margin="0,0,0,8" />
<StackPanel>
<TextBlock x:Name="deleteMsg" Text="Are you sure?"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<!-- yes Button -->
<Button
Content="Yes"
FontSize="16"
Padding="10,5"
Click="YesBtnClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#A4275D"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
<!-- No Button -->
<Button
Content="No"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="OnIgnorePopupOverlayPointerPressed">
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Delet Popup -->
<Border x:Name="tempErrorPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="Temperature Error!!"
FontSize="20"
FontWeight="Bold"
Foreground="Red"
Margin="0,0,0,8" />
<StackPanel>
<TextBlock x:Name="tempErrorMsg" Text="Error locating temperature do you want to stop?"
FontSize="16"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="10">
<!-- yes Button -->
<Button
Content="Yes"
FontSize="16"
Padding="10,5"
Click="ErrorYesBtnClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#A4275D"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
<!-- No Button -->
<Button
Content="No"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="HideTempErrorPopUp">
<Button.Styles>
<Style Selector="Button.SpecialButtonStyle:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/Settings.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using AvaloniaApplication1.DataBase;
using DaireApplication.DataBase;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using System;
using System.Drawing;
using System.Reflection.PortableExecutable;
using System.Threading;
namespace DaireApplication;
public partial class Settings : UserControl
{
Button controllButton = new Button();
private MainWindow? _mainWindow;
private UserTable? _currentUser;
public RecipeTable? _recipeTable;
private MachineTable _machine;
public string ActiveColor { get; set; } = "#A4275D";
public string PassiveColor { get; set; } = "#666666";
public Settings()
{
InitializeComponent();
}
public Settings(MainWindow mainWindow, UserTable currentUser,RecipeTable recipeTable)
{
_currentUser = currentUser;
_mainWindow = mainWindow;
_recipeTable = recipeTable;
_machine = new MachineTable();
_machine = _machine.ReadMachine();
InitializeComponent();
setDefaultSettings();
setDafaultValues();
mixerBtn.Click += _mainWindow.MotorClick;
fountainBtn.Click += _mainWindow.FountainClick;
}
private void toggelOnOffClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var StackPanel = button.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var titelLable = Label[0] as Label;
if (Label[1] is Label targetLable)
{
if (targetLable.Content == "ON")
{
if (titelLable.Content == "MOLD HEATER")
{
_mainWindow.moldHeaterMotor = 0;
}
if (titelLable.Content == "VIBRATION")
{
_mainWindow.vibrationMotor = 0;
}
if (titelLable.Content == "VIB. HEATER")
{
_mainWindow.vibHeaterMotor = 0;
}
}
else
{
if (titelLable.Content == "MOLD HEATER")
{
_mainWindow.moldHeaterMotor = 1;
}
if (titelLable.Content == "VIBRATION")
{
_mainWindow.vibrationMotor = 1;
}
if (titelLable.Content == "VIB. HEATER")
{
_mainWindow.vibHeaterMotor = 1;
}
}
}
}
}
private void PedalBtn(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
RecipeTable recipe = new RecipeTable();
recipe.Id = _recipeTable.Id;
var StackPanel = button.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[1] as Avalonia.Controls.Shapes.Rectangle;
if (Label[0] is TextBlock targetLable)
{
if (targetLable.Text == "AUTO")
{
if (_mainWindow.pedalOnTimer!=null )
{
_mainWindow.pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
_mainWindow.pedalOnTimer = null;
_mainWindow.pedalOnSeconds = 0;
}
if (_mainWindow.pedalOffTimer!=null)
{
_mainWindow.pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
_mainWindow.pedalOffTimer = null;
_mainWindow.pedalOffSeconds = 0;
}
_mainWindow.pedalMotor = 0;
targetLable.Text = "MANUAL";
underLine.Fill = Brush.Parse("#666666");
PedalAutoContainer.IsEnabled = false;
recipe.Pedal = true;
}
else
{
_mainWindow.pedalMotor = 1;
_mainWindow.pedalState = -1;
_mainWindow.setPedalTimerOnce = 1;
_mainWindow.pedalOnSeconds = 0;
_mainWindow.pedalOffSeconds = 0;
targetLable.Text = "AUTO";
underLine.Fill = Brush.Parse("#A4275D");
PedalAutoContainer.IsEnabled = true;
recipe.Pedal = false;
}
_recipeTable.UpdateRecipe(recipe);
}
}
}
private void adjustPedalTime(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
RecipeTable recipe = new RecipeTable();
recipe.Id = _recipeTable.Id;
if (button.Classes[0].ToString()== "PedalOff")
{
if (button.Content == "")
{
if (Int32.Parse(PedalOffTime.Text) > 0)
{
PedalOffTime.Text = (Int32.Parse(PedalOffTime.Text) - 1).ToString();
}
}
else if (button.Content == "+")
{
PedalOffTime.Text = (Int32.Parse(PedalOffTime.Text) + 1).ToString();
}
recipe.PedalOffTime = Int32.Parse(PedalOffTime.Text);
_recipeTable.UpdateRecipe(recipe);
}
else
{
if (button.Content == "")
{
if (Int32.Parse(PedalOnTime.Text) > 0)
{
PedalOnTime.Text = (Int32.Parse(PedalOnTime.Text) - 1).ToString();
}
}
else if (button.Content == "+")
{
if (int.TryParse(PedalOnTime.Text, out int value))
{
if (value < 9)
{
PedalOnTime.Text = (value + 1).ToString();
}
}
}
recipe.PedalOnTime = Int32.Parse(PedalOnTime.Text);
_recipeTable.UpdateRecipe(recipe);
}
_recipeTable = _recipeTable.ReadRecipesById(_recipeTable.Id.ToString());
}
}
private async void OnIgnorePopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
DeletePopupOverlay.IsVisible = false;
}
private async void HideTempErrorPopUp(object? sender, RoutedEventArgs e)
{
_mainWindow.pauseTimer = false;
_mainWindow.pauseTempTracking = true;
tempErrorPopupOverlay.IsVisible = false;
}
private async void YesBtnClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (DeletePopupOverlay.Tag=="home")
{
_mainWindow.resetAll();
// rest the board
_mainWindow.restBoard = true;
_mainWindow.UserName.Content = "Select User";
_mainWindow.footerMsg.Text = "";
_mainWindow.ContentArea.Content = new Home(_mainWindow);
}
else if (DeletePopupOverlay.Tag == "recipeSel")
{
_mainWindow.resetAll();
// rest the board
_mainWindow.restBoard = true;
_mainWindow.footerMsg.Text = "";
_mainWindow.ContentArea.Content = new Recipe(_mainWindow, Program.currentUser);
}
}
}
private async void ErrorYesBtnClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
//_mainWindow.pause = true;
//_mainWindow.pauseTempTracking = true;
//_mainWindow.pauseTimer = true;
// stop the recipe
_mainWindow.startRecipe = 0;
_mainWindow.Heating = 0;
_mainWindow.cooling = 0;
_mainWindow.pouring = 0;
_mainWindow.PumbOn = -1;
_mainWindow.pedalMotor = -1;
if (_mainWindow.heatingTimer != null)
{
_mainWindow.heatingTimer.Change(Timeout.Infinite, Timeout.Infinite);
_mainWindow.heatingSeconds = 0;
}
if (_mainWindow.coolingTimer != null)
{
_mainWindow.coolingTimer.Change(Timeout.Infinite, Timeout.Infinite);
_mainWindow.coolingSeconds = 0;
}
if (_mainWindow.pouringTimer != null)
{
_mainWindow.pouringTimer.Change(Timeout.Infinite, Timeout.Infinite);
_mainWindow.pouringSeconds = 0;
}
var fount = _mainWindow._mapping.Find(x => x.Name.ToLower() == "Pump".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
foreach (var bit in fount.BitNumbers)
{
_mainWindow.holdingRegister.motor &= (ushort)~(1 << bit);
}
}
}
_mainWindow.holdingRegister.setTemp1 = -10000;
_mainWindow.holdingRegister.setTemp2 = -10000;
_mainWindow.holdingRegister.setTemp3 = -10000;
_mainWindow.holdingRegister.setTemp4 = -10000;
await _mainWindow.WriteToSerialAsync("ErrorYesBtnClick");
tempErrorPopupOverlay.IsVisible = false;
_mainWindow.footerMsg.Text = "Recipe Stoped";
_mainWindow.recipeStartBtn.Content = "START RECIPE";
}
}
private void setDefaultSettings()
{
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
//_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = true;
_mainWindow.RecipeSelPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RunInterfaceTrack.IsVisible = true;
_mainWindow.RunInterfacePolygon.Stroke = Brush.Parse("#A4275D");
_mainWindow.RecipePanelTrack.IsVisible = false;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.DiagnosticsTrack.IsVisible = false;
_mainWindow.TitleBtn.IsVisible = true;
_mainWindow.Title.Text = _recipeTable.Name;
//Set Footer
_mainWindow.footerMsg.Text = "Ready";
_mainWindow.footerMsg.MaxWidth = 500;
_mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke;
_mainWindow.footerMsg.Foreground = Avalonia.Media.Brushes.Green;
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = true;
_mainWindow.adminBtns.IsVisible = false;
}
private void setDafaultValues()
{
//Recipe Settings
heatingValue.Content = _recipeTable.HeatingGoal;
coolingValue.Content = _recipeTable.CoolingGoal;
pouringValue.Content = _recipeTable.PouringGoal;
//tankTemp
TankTempValue.Content = _recipeTable?.TankTemp;
//mixer
var mixerChildren= MixerSP.Children;
var mixerLable = mixerChildren[1] as Label;
mixerLable.Content = _recipeTable.Mixer.Value ? "ON" : "OFF";
var mixerUnderLine = mixerChildren[2] as Avalonia.Controls.Shapes.Rectangle;
mixerUnderLine.Fill = _recipeTable.Mixer.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor);
//pedal
var pedalChildren = PedalSP.Children;
var pedalText = pedalChildren[0] as TextBlock;
var pedalUnderLine = pedalChildren[1] as Avalonia.Controls.Shapes.Rectangle;
if (_recipeTable.Pedal.Value)
{
pedalText.Text = "MANUAL";
pedalUnderLine.Fill = Brush.Parse(PassiveColor);
PedalAutoContainer.IsEnabled = false;
}
else
{
pedalText.Text = "AUTO";
pedalUnderLine.Fill = Brush.Parse(ActiveColor);
PedalAutoContainer.IsEnabled = true;
}
PedalOffTime.Text = _recipeTable.PedalOffTime.ToString();
PedalOnTime.Text = _recipeTable.PedalOnTime.ToString();
//fountain Temp
FountainTempValue.Content = _recipeTable?.FountainTemp;
//fountain
var fountainChildren = FountainSP.Children;
var fountainLable = fountainChildren[1] as Label;
fountainLable.Content = _recipeTable.Fountain.Value ? "ON" : "OFF";
var fountainUnderLine = fountainChildren[2] as Avalonia.Controls.Shapes.Rectangle;
fountainUnderLine.Fill = _recipeTable.Fountain.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor);
//mold Heater
var moldHeaterChildren = MoldHeaterSP.Children;
var moldHeaterLable = moldHeaterChildren[1] as Label;
moldHeaterLable.Content = _recipeTable.MoldHeater.Value ? "ON" : "OFF";
var moldHeaterUnderLine = moldHeaterChildren[2] as Avalonia.Controls.Shapes.Rectangle;
moldHeaterUnderLine.Fill = _recipeTable.MoldHeater.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor);
// vibration
var vibrationChildren = VibrationSP.Children;
var vibrationLable = vibrationChildren[1] as Label;
vibrationLable.Content = _recipeTable.Vibration.Value ? "ON" : "OFF";
var vibrationUnderLine = vibrationChildren[2] as Avalonia.Controls.Shapes.Rectangle;
vibrationUnderLine.Fill = _recipeTable.Vibration.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor);
// vib heater
var vibHeaterChildren = VibHeaterSP.Children;
var vibHeaterLable = vibHeaterChildren[1] as Label;
vibHeaterLable.Content = _recipeTable.VibHeater.Value ? "ON" : "OFF";
var vibHeaterUnderLine = vibHeaterChildren[2] as Avalonia.Controls.Shapes.Rectangle;
vibHeaterUnderLine.Fill = _recipeTable.VibHeater.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor);
}
}
============================================================
FILE: DaireApplication/Views/UserController/Software.axaml
============================================================
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DaireApplication"
x:DataType="local:Software"
Width="1280" Height="620" Background="#b3b3b3"
x:Class="DaireApplication.Software"
>
<UserControl.Styles>
<Style Selector="ComboBox.noArrow">
<Setter Property="Template">
<ControlTemplate TargetType="ComboBox">
<Grid>
<ToggleButton x:Name="PART_Button"
Focusable="False"
ClickMode="Press"
IsChecked="{Binding IsDropDownOpen,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}"
Background="#E6E6E6"
Width="210" Height="40">
<Border Background="#E6E6E6"
CornerRadius="8"
Padding="0,0">
<ContentPresenter x:Name="PART_SelectionBoxPresenter"
Content="{TemplateBinding SelectionBoxItem}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="20"
Foreground="#af196f"/>
</Border>
</ToggleButton>
<Popup x:Name="PART_Popup"
PlacementTarget="{Binding #PART_Button}"
Placement="Bottom"
IsOpen="{Binding IsDropDownOpen,
RelativeSource={RelativeSource TemplatedParent},
Mode=TwoWay}">
<Border Background="White"
BorderBrush="Gray"
BorderThickness="1">
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TextBlock.lbl">
<Setter Property="Foreground" Value="#000000"/>
</Style>
<Style Selector="ComboBoxItem">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
<Style Selector="ComboBoxItem:selectable:checked">
<Setter Property="Foreground" Value="#af196f"/>
</Style>
<Style Selector="ComboBoxItem:pointerover">
<Setter Property="Foreground" Value="#af196f"/>
<Setter Property="Background" Value="Transparent"/>
</Style>
</UserControl.Styles>
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*">
<Border Grid.Column="0" Padding="10">
<StackPanel Spacing="8">
<!--box-->
<Border Width="222" Height="224" Background="#f9f9f9" CornerRadius="10" Padding="10" ZIndex="100" >
<StackPanel Spacing="5">
<TextBlock
Foreground="#918f90"
FontSize="20.5" HorizontalAlignment="Center"
VerticalAlignment="Center">PASSWORDS RESET</TextBlock>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5">
<Button Background="Transparent"
Width="210"
Click="showChangePasswordPopUp">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" Classes="user">
ADMINISTRATOR
</TextBlock>
</Button>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5">
<Button Background="Transparent" Width="210"
Click="showChangePasswordPopUp">
<TextBlock Classes="user"
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center">
CHEF
</TextBlock>
</Button>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5">
<Button Background="Transparent" Width="210" Click="showChangePasswordPopUp">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" Classes="user">
OPERATOR1
</TextBlock>
</Button>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5">
<Button Background="Transparent" Width="210" Click="showChangePasswordPopUp">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" Classes="user">
OPERATOR2
</TextBlock>
</Button>
</Border>
</StackPanel>
</Border>
<!--box1 -->
<Border Width="222" Height="178" Background="#f9f9f9" CornerRadius="10" Padding="10" ZIndex="100">
<StackPanel Spacing="5">
<TextBlock
Foreground="#918f90"
FontSize="20.5"
HorizontalAlignment="Center"
VerticalAlignment="Center">SCREEN SETTINGS</TextBlock>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5" >
<Button Background="Transparent"
Width="210" Height="40" Click="showScreenPopUp" Tag="BRIGHTNESS" >
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" Grid.Column="0">
BRIGHTNESS
</TextBlock>
<StackPanel Grid.Column="1" Orientation="Horizontal"
HorizontalAlignment="Right">
<TextBlock
Foreground="#af196f"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center"
x:Name="brightnessValue"
>
80
</TextBlock>
<TextBlock
Foreground="#af196f"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center">
%
</TextBlock>
</StackPanel>
</Grid>
</Grid>
</Button>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5" >
<Button Background="Transparent"
Width="210"
Height="40" Click="showScreenPopUp" Tag="AUTO DIM">
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" Grid.Column="0">
AUTO DIM
</TextBlock>
<StackPanel Grid.Column="1" Orientation="Horizontal"
Spacing="5" HorizontalAlignment="Right">
<TextBlock
Foreground="#af196f"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center"
x:Name="dimValue"
>
60
</TextBlock>
<TextBlock
Foreground="#af196f"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center">
Min
</TextBlock>
</StackPanel>
</Grid>
</Grid>
</Button>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5" >
<Button Background="Transparent"
Width="210"
Height="40" Click="showScreenPopUp" Tag="AUTO OFF">
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" Grid.Column="0">
AUTO OFF
</TextBlock>
<StackPanel Grid.Column="1" Orientation="Horizontal"
Spacing="5" HorizontalAlignment="Right">
<TextBlock
Foreground="#af196f"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center"
x:Name="offValue"
>
90
</TextBlock>
<TextBlock
Foreground="#af196f"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center">
Min
</TextBlock>
</StackPanel>
</Grid>
</Grid>
</Button>
</Border>
</StackPanel>
</Border>
<!--box-->
<Border Width="222" Height="178" Background="#f9f9f9" CornerRadius="10" Padding="10" >
<StackPanel Spacing="5">
<TextBlock
Foreground="#918f90"
FontSize="20.5"
HorizontalAlignment="Center"
VerticalAlignment="Center">COM SETTINGS</TextBlock>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5" Padding="0" >
<Grid RowDefinitions="*">
<Grid Grid.Row="0" ColumnDefinitions="Auto,*">
<ComboBox x:Name="portComboBox"
Margin="0"
Classes="noArrow"
SelectedIndex="0"
SelectedItem="{Binding SelectedPort}"
ItemsSource="{Binding SerialPorts, Mode=OneWay}"
SelectionChanged="portChanged" >
</ComboBox>
<StackPanel Grid.Column="1" Orientation="Horizontal"
HorizontalAlignment="Right">
</StackPanel>
</Grid>
</Grid>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5" Padding="0" >
<Button Background="Transparent"
Width="210"
Click="showComPopUp">
<TextBlock
Foreground="#231f20"
FontSize="20.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" >
COM Settings
</TextBlock>
</Button>
</Border>
<!--row-->
<Border Width="210" Height="40" Background="#e6e6e6" CornerRadius="5" Padding="0" >
<Button Background="Transparent"
Width="210"
Click="ShowTempPopUp">
<TextBlock
Foreground="#231f20"
FontSize="18.5"
VerticalAlignment="Center"
HorizontalAlignment="Center" >
Temperature Settings
</TextBlock>
</Button>
</Border>
</StackPanel>
</Border>
</StackPanel>
</Border>
<Grid Grid.Column="1"></Grid>
</Grid>
<!-- Overlay Background for Add Popup -->
<Border x:Name="passwordPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="hidePasswordPopUp">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid x:Name="NameModule" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True" PointerPressed="InnerPopupPointerPressed">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="titelMsg" Text="New Addministrator Password:"
FontSize="18"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
<Border Name="passwordBorder">
<TextBox x:Name="passwordInput"
Width="300"
Height="30"
BorderBrush="#CCC"
BorderThickness="1"
MaxLength="9"
Tag="password"
></TextBox>
</Border>
<!-- Local styles for this specific TextBox -->
<CheckBox x:Name="isActivePass" Content="Enable/Disable" Foreground="Black">
<CheckBox.Styles>
<Style Selector="CheckBox">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="FontSize" Value="14"/>
</Style>
<Style Selector="CheckBox:checked">
<Setter Property="Foreground" Value="Teal"/>
</Style>
</CheckBox.Styles>
</CheckBox>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
<!-- Save Button -->
<Button x:Name="SaveButton"
Content="OK"
FontSize="16"
Padding="10,5"
Click="passwordSaveClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Effect>
</Button.Effect>
</Button>
<!-- Cancel Button -->
<Button x:Name="CancelButton"
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="hidePasswordPopUp"
>
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Add Popup -->
<Border x:Name="secreenPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" PointerPressed="hideScreenPopUp">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC" >
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="titelSecreenMsg" Text="Enter Brightness percentage:"
FontSize="18"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
<TextBlock x:Name="sliderValue" Margin="0,10,0,0" Foreground="Black">0</TextBlock>
<Slider x:Name="slider" Minimum="0" Maximum="120"
TickFrequency="1"
IsSnapToTickEnabled="True"
Background="Black"
ValueChanged="OnSliderValueChanged"/>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
<!-- Save Button -->
<Button x:Name="secreenSaveButton"
Content="OK"
FontSize="16"
Padding="10,5"
Click="screenSaveClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Effect>
</Button.Effect>
</Button>
<!-- Cancel Button -->
<Button x:Name="CancelScreenButton"
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="hideScreenPopUp"
>
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Com Settings Popup -->
<Border x:Name="comPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" PointerPressed="hideComPopUp">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC" >
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock Text="Com Settings"
FontSize="18"
FontWeight="Bold"
Foreground="#333"
Margin="0,0,0,8" />
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0" Foreground="Black">Bound Rate:</TextBlock>
</StackPanel>
<ComboBox
x:Name="boundRateComboBox"
Margin="0"
HorizontalAlignment="Center"
Classes="noArrow"
SelectedIndex="0"
>
<ComboBoxItem Tag="0" Content="9600"/>
<ComboBoxItem Tag="1" Content="14400"/>
<ComboBoxItem Tag="2" Content="19200"/>
<ComboBoxItem Tag="3" Content="28800"/>
<ComboBoxItem Tag="4" Content="38400"/>
<ComboBoxItem Tag="5" Content="57600"/>
<ComboBoxItem Tag="6" Content="115200"/>
</ComboBox>
</StackPanel>
<StackPanel>
<TextBlock Foreground="Black" Margin="0,0,0,5">Stop Bits:</TextBlock>
<ComboBox
x:Name="stopBitsComboBox"
Margin="0"
HorizontalAlignment="Center"
Classes="noArrow"
SelectedIndex="0"
>
<ComboBoxItem Tag="0" Content="0"/>
<ComboBoxItem Tag="1" Content="1"/>
<ComboBoxItem Tag="2" Content="2"/>
<ComboBoxItem Tag="3" Content="1.5"/>
</ComboBox>
</StackPanel>
<StackPanel>
<TextBlock Foreground="Black" Margin="0,0,0,5">Parity:</TextBlock>
<ComboBox
x:Name="parityComboBox"
Margin="0"
HorizontalAlignment="Center"
Classes="noArrow"
SelectedIndex="0"
>
<ComboBoxItem Tag="0" Content="NONE"/>
<ComboBoxItem Tag="1" Content="ODD"/>
<ComboBoxItem Tag="2" Content="EVEN"/>
<ComboBoxItem Tag="4" Content="SPACE"/>
<ComboBoxItem Tag="3" Content="MARK"/>
</ComboBox>
</StackPanel>
<StackPanel>
<TextBlock Foreground="Black" Margin="0,0,0,5">Packets Sending Intervals :</TextBlock>
<TextBox x:Name="sendingTimetxt"
BorderBrush="#CCC"
BorderThickness="1"
GotFocus="ShowNumberKeyBoard"
MaxLength="9"
></TextBox>
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
<!-- Save Button -->
<Button x:Name="comSaveButton"
Content="OK"
FontSize="16"
Padding="10,5"
Click="comSaveClick"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Effect>
</Button.Effect>
</Button>
<!-- Cancel Button -->
<Button x:Name="CancelComButton"
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="hideComPopUp"
>
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Com Settings Popup -->
<Border x:Name="tempPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" PointerPressed="hideTempPopUp">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="InnerPopupPointerPressed" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC" >
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<StackPanel Spacing="10">
<TextBlock Foreground="Black" Margin="0,0,0,5">Warning Limit :</TextBlock>
<Border x:Name="warningBorder">
<TextBox x:Name="warningLimit"
BorderBrush="#CCC"
BorderThickness="1"
MaxLength="9"
></TextBox>
</Border>
<TextBlock Foreground="Black" Margin="0,0,0,5">Error Limit :</TextBlock>
<Border x:Name="errorBorder">
<TextBox x:Name="errorLimit"
BorderBrush="#CCC"
BorderThickness="1"
MaxLength="9"
></TextBox>
</Border>
</StackPanel>
<!-- Button Panel -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Spacing="10">
<!-- Save Button -->
<Button x:Name="tempSaveButton"
Content="OK"
FontSize="16"
Padding="10,5"
Click="tempSaveBtn"
Foreground="White" >
<Button.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="#A4275D" Offset="0" />
<GradientStop Color="#A4275D" Offset="1" />
</LinearGradientBrush>
</Button.Background>
<Button.Effect>
</Button.Effect>
</Button>
<!-- Cancel Button -->
<Button x:Name="CancelTempButton"
Content="Cancel"
FontSize="16"
Padding="10,5"
Background="Gray"
Foreground="White"
Click="hideTempPopUp"
>
<Button.Effect>
</Button.Effect>
</Button>
</StackPanel>
</StackPanel>
</Border>
</Grid>
</Border>
<!--number keyBoard-->
<Border x:Name="keyBoardPopup"
Background="#80000000"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="False"
ZIndex="50"
PointerPressed="OnPopupOverlayPointerPressed">
<Grid MaxWidth="500" MaxHeight="500" HorizontalAlignment="Right" VerticalAlignment="Center"
Margin="0,0,150,0">
<Border x:Name="PopupControl"
BorderThickness="2"
CornerRadius="10"
Padding="10"
PointerPressed="OnPopupOverlayPointerPressed">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center" Spacing="10">
<!-- Popup Content (Keypad etc.) -->
<Grid IsVisible="True">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="100"/>
<Setter Property="FontSize" Value="50"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="White"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="RenderTransform" Value="scale(1.11)"/>
</Style>
</Grid.Styles>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="1" Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<!-- Keypad Buttons -->
<Button Content="1" Grid.Row="0" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="2" Grid.Row="0" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="3" Grid.Row="0" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="4" Grid.Row="1" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="5" Grid.Row="1" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="6" Grid.Row="1" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="7" Grid.Row="2" Grid.Column="0" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="8" Grid.Row="2" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="9" Grid.Row="2" Grid.Column="2" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="BACK" Grid.Row="3" Grid.Column="0" FontSize="20" Background="#D3D3D3" Margin="5" Click="OnBackClick"/>
<Button Content="0" Grid.Row="3" Grid.Column="1" FontSize="24" Background="White" Margin="5" Click="OnKeyClick"/>
<Button Content="ENTER" Grid.Row="3" Grid.Column="2" FontSize="20" Background="#A4275D" Foreground="White" Margin="5" Click="EnterClick"/>
</Grid>
</Grid>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>
============================================================
FILE: DaireApplication/Views/UserController/Software.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Threading;
using AvaloniaApplication1.DataBase;
using DaireApplication.DataBase;
using DaireApplication.ViewModels;
using DaireApplication.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Numerics;
using System.Reflection.Emit;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace DaireApplication;
public partial class Software : UserControl
{
private MainWindow? _mainWindow;
public UserTable _user = new();
public ScreeenTable _screeen = new();
private Process? _keyboardProcess;
private bool _isWindowLoaded = false;
TextBox targetText = new TextBox();
int oldValue = 0;
bool _isAdvSetting;
bool _isFromManualControl;
public event PropertyChangedEventHandler? PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] string? name = null) =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
public ObservableCollection<string> SerialPorts { get; } = new() { "Choose COM" };
private string? _selectedPort;
public string? SelectedPort
{
get => _selectedPort;
set
{
if (_selectedPort != value)
{
_selectedPort = value;
RaisePropertyChanged();
}
}
}
public Software(MainWindow mainWindow,bool isAdvSetting=false, bool isFromManualControl=false)
{
_mainWindow = mainWindow;
_isAdvSetting = isAdvSetting;
_isFromManualControl = isFromManualControl;
foreach (var port in SerialPort.GetPortNames())
{
SerialPorts.Add(port);
}
var screen = _screeen.ReadScreens()[0];
InitializeComponent();
this.Loaded += OnWindowLoaded;
if (SerialPorts.Count - 1 > 0)
{
if (!string.IsNullOrEmpty(screen.port))
{
SerialPorts[0] = "Close Comunication";
SelectedPort = screen.port;
}
else
{
SerialPorts[0] = "Choose COM";
SelectedPort = SerialPorts[0];
}
}
else
SelectedPort = SerialPorts[0];
DataContext = this;
setDefaultSettings();
showDefaultValues();
sendingTimetxt.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
warningLimit.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
errorLimit.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel);
passwordBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
warningBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
errorBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true);
AttachHandlers(_mainWindow.logoBtn, AdvanceSettingsView);
AttachHandlers(_mainWindow.UserName, CloseApplication);
}
public void AttachHandlers(Button button, System.EventHandler<Avalonia.Input.HoldingRoutedEventArgs> func)
{
if (button != null)
{
button.Holding += func;
button.PointerPressed += (sender, e) =>
{
// Simulate a long press on any pointer (mouse or touch)
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type));
};
button.PointerReleased += (sender, e) =>
{
// End simulated long press
var point = e.GetPosition(button);
func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type));
};
}
}
public Software()
{
InitializeComponent();
}
public void AdvanceSettingsView(object? sender, RoutedEventArgs e)
{
if (_mainWindow.ContentArea.Content == this)
{
_mainWindow.ContentArea.Content = new AdvanceSettings(_mainWindow,false,true);
}
}
public static void CloseApplication(object? sender, RoutedEventArgs e)
{
var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime;
lifetime?.Shutdown(); // This should correctly shut down the application
}
private void OnWindowLoaded(object? sender, RoutedEventArgs e)
{
_isWindowLoaded = true;
}
private void OnTextInput(object? sender, TextInputEventArgs e)
{
if (sender is TextBox textBox)
{
string newText = textBox.Text + e.Text;
if (!Regex.IsMatch(newText, @"^\d*\.?\d*$"))
{
e.Handled = true;
}
}
}
private void hidePasswordPopUp(object sender, RoutedEventArgs e)
{
passwordInput.Text = "";
CloseKeyboard();
passwordPopupOverlay.IsVisible = false;
}
private async void passwordSaveClick(object? sender, RoutedEventArgs e)
{
var user = _user.ReadUsers().FirstOrDefault(x=>x.UserName.ToLower()==titelMsg.Tag.ToString().ToLower());
user.Password = passwordInput.Text;
user.IsActive = isActivePass.IsChecked.Value;
if (_user.UpdateUser(user))
{
//await MainWindow.MessageBox.Show(_mainWindow, "Password Changed Sucseccfully", "Sucsecc");
passwordInput.Text = "";
CloseKeyboard();
passwordPopupOverlay.IsVisible = false;
}
else
{
if (_keyboardProcess != null)
{
_keyboardProcess.Kill();
}
await MainWindow.MessageBox.Show(_mainWindow, "Password Does Not Changed Try Again", "Error");
_mainWindow.Topmost = false;
}
}
private void showChangePasswordPopUp(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var text = button.Content as TextBlock;
titelMsg.Text = $"New {text.Text} Password:";
titelMsg.Tag = text.Text;
var user = _user.ReadUsers().FirstOrDefault(x => x.UserName.ToLower() == titelMsg.Tag.ToString().ToLower());
isActivePass.IsVisible = true;
isActivePass.IsChecked = user.IsActive;
passwordPopupOverlay.IsVisible = true;
}
}
private void hideScreenPopUp(object sender, RoutedEventArgs e)
{
slider.Value = 0;
secreenPopupOverlay.IsVisible = false;
}
private async void screenSaveClick(object? sender, RoutedEventArgs e)
{
var screenData = _screeen.ReadScreens()?[0];
string brightnessPath = "/sys/class/backlight/backlight/brightness"; // Try backlight1 if this fails
if (titelSecreenMsg.Tag.ToString()== "BRIGHTNESS")
{
try
{
if (!string.IsNullOrEmpty(sliderValue.Text))
{
int brightnessValue = (int)(Int32.Parse(sliderValue.Text) / 100.0 * 255);
screenData.brightness = Int32.Parse(sliderValue.Text);
_screeen.UpdateScreen(screenData);
File.WriteAllText(brightnessPath, brightnessValue.ToString());
}
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
else if (titelSecreenMsg.Tag.ToString() == "AUTO DIM")
{
if (!string.IsNullOrEmpty(sliderValue.Text))
{
if ((screenData?.offSec / 60.0) < float.Parse(sliderValue.Text))
{
if (_keyboardProcess != null)
{
_keyboardProcess.Kill();
}
await MainWindow.MessageBox.Show(_mainWindow, "AutoOff Value must be greater than AutoDim Value", "Error");
_mainWindow.Topmost = false;
return;
}
screenData.dimSec = float.Parse(sliderValue.Text) * 60;
_screeen.UpdateScreen(screenData);
}
}
else if (titelSecreenMsg.Tag.ToString() == "AUTO OFF")
{
if (!string.IsNullOrEmpty(sliderValue.Text))
{
if ((screenData?.dimSec / 60.0)> float.Parse(sliderValue.Text))
{
if (_keyboardProcess != null)
{
_keyboardProcess.Kill();
}
await MainWindow.MessageBox.Show(_mainWindow, "AutoOff Value must be greater than AutoDim Value", "Error");
_mainWindow.Topmost = false;
return;
}
screenData.offSec = float.Parse(sliderValue.Text) * 60;
_screeen.UpdateScreen(screenData);
}
}
showDefaultValues();
secreenPopupOverlay.IsVisible = false;
}
private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e)
{
e.Handled = true;
}
private void showScreenPopUp(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var screenData = _screeen.ReadScreens()?[0];
if (button.Tag.ToString() == "BRIGHTNESS")
{
slider.Maximum = 100;
titelSecreenMsg.Text = $"Enter {button.Tag} percentage:";
titelSecreenMsg.Tag = button.Tag;
slider.Value = screenData.brightness;
secreenPopupOverlay.IsVisible = true;
}
if (button.Tag.ToString() == "AUTO DIM")
{
slider.Maximum = 120;
titelSecreenMsg.Text = $"Enter {button.Tag} value in min:";
titelSecreenMsg.Tag = button.Tag;
slider.Value = screenData.dimSec / 60;
secreenPopupOverlay.IsVisible = true;
}
if (button.Tag.ToString() == "AUTO OFF")
{
slider.Maximum = 120;
titelSecreenMsg.Text = $"Enter {button.Tag} value in min:";
titelSecreenMsg.Tag = button.Tag;
slider.Value = screenData.offSec / 60;
secreenPopupOverlay.IsVisible = true;
}
}
}
private void OnSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (sender is Slider slider)
{
var parent = slider.Parent as StackPanel;
var targetText = parent.Children[1] as TextBlock;
targetText.Text= slider.Value.ToString();
//sliderValue.Text= slider.Value.ToString();
}
}
private void changeValueClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
var parent = button.Parent as StackPanel;
var slider = parent.Children[1] as Slider;
var grandParent = parent.Parent as StackPanel;
var stack = grandParent.Children[0] as StackPanel;
var targetText = stack.Children[1] as TextBlock;
targetText.Text = slider.Value.ToString();
if (button.Content=="+") // +
{
slider.Value = Int32.Parse(targetText.Text) + 1;
}
else // -
{
if (Int32.Parse(targetText.Text)>0)
{
slider.Value = Int32.Parse(targetText.Text) - 1;
}
}
}
}
private void OnComSliderValueChanged(object? sender, RoutedEventArgs e)
{
if (sender is Slider slider)
{
var parent = slider.Parent.Parent as StackPanel;
var stack = parent.Children[0] as StackPanel;
var targetText = stack.Children[1] as TextBlock;
targetText.Text= slider.Value.ToString();
}
}
private void hideComPopUp(object sender, RoutedEventArgs e)
{
//comSlider.Value = 0;
comPopupOverlay.IsVisible = false;
}
private void hideTempPopUp(object sender, RoutedEventArgs e)
{
tempPopupOverlay.IsVisible = false;
}
private async void comSaveClick(object? sender, RoutedEventArgs e)
{
var screen = _screeen.ReadScreens()[0];
var boundRateItem = boundRateComboBox.SelectedItem as ComboBoxItem;
screen.boundRate = Int32.Parse(boundRateItem.Content.ToString());
var stopbitsItem = stopBitsComboBox.SelectedItem as ComboBoxItem;
screen.stopBits = Int32.Parse(stopbitsItem.Tag.ToString());
var parityItem = parityComboBox.SelectedItem as ComboBoxItem;
screen.parity = Int32.Parse(parityItem.Tag.ToString());
screen.sendingTime = Int32.Parse(sendingTimetxt.Text);
if (_screeen.UpdateScreen(screen))
{
_mainWindow.resetPort = true;
_mainWindow.footerMsg.Text = "Connecting.....";
_mainWindow.footerMsg.IsVisible = true;
comPopupOverlay.IsVisible = false;
}
}
private void showComPopUp(object? sender, RoutedEventArgs e)
{
var screen = _screeen.ReadScreens()[0];
boundRateComboBox.SelectedIndex=int.Parse(boundRateComboBox.Items.OfType<ComboBoxItem>().FirstOrDefault(item => item.Content?.ToString() == screen.boundRate.ToString()).Tag.ToString());
stopBitsComboBox.SelectedIndex = screen.stopBits;
parityComboBox.SelectedIndex = screen.parity;
sendingTimetxt.Text=screen.sendingTime.ToString();
comPopupOverlay.IsVisible = true;
}
private void ShowTempPopUp(object? sender, RoutedEventArgs e)
{
var screen = _screeen.ReadScreens()[0];
warningLimit.Text=screen.warningLimit.ToString();
errorLimit.Text=screen.errorLimit.ToString();
tempPopupOverlay.IsVisible = true;
}
private void tempSaveBtn(object? sender, RoutedEventArgs e)
{
var screen = _screeen.ReadScreens()[0];
screen.warningLimit = double.Parse(warningLimit.Text);
screen.errorLimit = double.Parse(errorLimit.Text);
_screeen.UpdateScreen(screen);
CloseKeyboard();
//if (_keyboardProcess != null)
//{
// _keyboardProcess.Kill();
//}
tempPopupOverlay.IsVisible=false;
}
private void portChanged(object? sender, RoutedEventArgs e)
{
if (!_isWindowLoaded)
return;
if (sender is ComboBox comboBox)
{
if (comboBox.SelectedItem is string selectedItem)
{
var screen = _screeen.ReadScreens()[0];
if (selectedItem.ToString()!= "Choose COM" && selectedItem.ToString()!= "Close Comunication")
{
screen.port = selectedItem.ToString();
_screeen.UpdateScreen(screen);
}
else
{
screen.port = "";
_screeen.UpdateScreen(screen);
}
boundRateComboBox.SelectedIndex = int.Parse(boundRateComboBox.Items.OfType<ComboBoxItem>().FirstOrDefault(item => item.Content?.ToString() == screen.boundRate.ToString()).Tag.ToString());
stopBitsComboBox.SelectedIndex = screen.stopBits;
parityComboBox.SelectedIndex = screen.parity;
sendingTimetxt.Text = screen.sendingTime.ToString();
this.comSaveButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
}
}
private (string? fileName, string args) GetKeyboardCommand()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return ("osk.exe", "");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return ("onboard", ""); // or "florence", "matchbox-keyboard"
return (null, "");
}
private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e)
{
if (_keyboardProcess is { HasExited: false })
return;
var (fileName, args) = GetKeyboardCommand();
if (fileName is null)
return;
_keyboardProcess = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileName,
Arguments = args,
UseShellExecute = true,
WorkingDirectory = "/usr/bin"
},
EnableRaisingEvents = true
};
try
{
_keyboardProcess.Start();
Dispatcher.UIThread.Post(() =>
{
if (sender is Border border)
{
var textbox = border.Child as TextBox;
textbox.SelectionStart = 0;
textbox.SelectionEnd = textbox.Text?.Length ?? 0;
}
});
}
catch
{
// fail silently if keyboard not found
}
}
private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e)
{
targetText.Text = oldValue.ToString();
CancelComButton.Focus();
keyBoardPopup.IsVisible = false;
}
private void OnKeyClick(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
targetText.Text += button.Content;
}
}
private void ShowNumberKeyBoard(object? sender, RoutedEventArgs e)
{
targetText = sendingTimetxt;
oldValue = Int32.Parse(targetText.Text);
targetText.Text = "";
keyBoardPopup.IsVisible = true;
}
private void OnBackClick(object? sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(targetText.Text))
{
// Remove the last character from the text box
targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1);
}
}
private void EnterClick(object? sender, RoutedEventArgs e)
{
CancelComButton.Focus();
keyBoardPopup.IsVisible = false;
}
private void CloseKeyboard()
{
try
{
if (_keyboardProcess != null)
{
// Kill the keyboard process
_keyboardProcess.Kill();
_keyboardProcess.Dispose();
_keyboardProcess = null;
// Force kill any remaining keyboard processes
var processKill = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = "killall",
Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards
UseShellExecute = false,
CreateNoWindow = true
}
};
processKill.Start();
processKill.WaitForExit(1000);
processKill.Dispose();
}
}
catch (Exception ex)
{
Console.WriteLine($"Error closing keyboard: {ex.Message}");
}
}
private void setDefaultSettings()
{
_mainWindow.minimizeBtn.IsVisible = false;
var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel;
if (_isFromManualControl)
{
// Special UI setup when called from ManualControl
_mainWindow.HomeTrack.IsVisible = true;
_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = true;
_mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeEditTrack.IsVisible = false;
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
_mainWindow.ManualControlTrack.IsVisible = true;
_mainWindow.ManualControlPolygon.Stroke = Avalonia.Media.Brushes.Black;
}
else
{
// Original logic for other callers
//Set Track Up
_mainWindow.HomeTrack.IsVisible = true;
_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.RecipeSelTrack.IsVisible = false;
_mainWindow.RunInterfaceTrack.IsVisible = false;
_mainWindow.RecipePanelTrack.IsVisible = false;
_mainWindow.RecipeEditTrack.IsVisible = false;
if (_isAdvSetting)
{
_mainWindow.SettingTrack.IsVisible = false;
_mainWindow.AdvanceSettingsTrack.IsVisible = true;
_mainWindow.AdvanceSettingsPolygon.Stroke = Avalonia.Media.Brushes.Black;
}
else
{
_mainWindow.SettingTrack.IsVisible = true;
_mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black;
_mainWindow.AdvanceSettingsTrack.IsVisible = false;
}
}
_mainWindow.DiagnosticsTrack.IsVisible = false;
// Remove the button from its current position
stackPanel.Children.Remove(_mainWindow.SoftwareTrack);
// Add it back at the end of the StackPanel
stackPanel.Children.Add(_mainWindow.SoftwareTrack);
_mainWindow.SoftwareTrack.IsVisible = true;
_mainWindow.SoftwarePolygon.Stroke = Brush.Parse("#A4275D");
_mainWindow.TitleBtn.IsVisible = false;
//Set Footer
_mainWindow.footerMsg.IsVisible = false;
_mainWindow.footer.Background = Brush.Parse("#f2f2f2");
_mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
_mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt");
_mainWindow.footerDateContainer.IsVisible = true;
_mainWindow.footerStartBtn.IsVisible = false;
_mainWindow.adminBtns.IsVisible = false;
}
private void showDefaultValues()
{
var users = _user.ReadUsers();
var allUIUsers = this.GetLogicalDescendants()
.OfType<TextBlock>()
.Where(cb => cb.Classes.Contains("user"))
.ToList();
for (int i = 0; i < allUIUsers.Count; i++)
{
allUIUsers[i].Text = users[i].UserName;
}
var screenData = _screeen.ReadScreens()?[0];
brightnessValue.Text = screenData?.brightness.ToString();
dimValue.Text = (screenData?.dimSec/60.0).ToString();
offValue.Text = (screenData?.offSec/60.0).ToString();
}
}
============================================================
FILE: DaireApplication/Views/MainWindow.axaml
============================================================
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:DaireApplication.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Class="DaireApplication.Views.MainWindow"
Icon="/Assets/avalonia-logo.ico"
Title="DaireApplication"
Background="#B3B3B3"
FontFamily="Helvetica"
WindowState="Maximized"
SystemDecorations="None"
Topmost="False"
Width="1280" Height="800">
<Grid RowDefinitions="Auto,2*,Auto">
<!-- Titel Bar-->
<Grid x:Name="TitelBar" Grid.Row="0" Background="WhiteSmoke" Height="90" Margin="0">
<Grid.Styles>
<Style Selector="Button">
<Setter Property="Background" Value="Transparent"></Setter>
</Style>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Background" Value="Transparent"></Setter>
</Style>
</Grid.Styles>
<Grid ColumnDefinitions="Auto,5*,Auto">
<StackPanel Width="160" Height="40" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Left" Grid.Column="0" Margin="0,0,40,0">
<Button x:Name="logoBtn" BorderThickness="0" Background="Transparent" Width="220" Height="200">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" BorderBrush="Transparent" BorderThickness="1" Background="Transparent">
<ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Button.Template>
<Image Source="/Assets/Logo.png" Width="160" Height="40" />
</Button>
</StackPanel>
<StackPanel Background="Transparent" HorizontalAlignment="Left" Grid.Column="1" Orientation="Horizontal" Spacing="-10" ZIndex="-1">
<!-- Home Button with One-Sided Arrow -->
<Button x:Name="HomeTrack" BorderThickness="2" Width="140" Height="60" Click="HomeTraclBtn" >
<Grid Width="140" Height="50" >
<Polygon x:Name="HomePolygon" Points="20,0 120,0 140,25 120,50 20,50 20,0"
Stroke="Black" StrokeThickness="2" Fill="#E6E6E6"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" >
<Image Source="/Assets/Home.png" Width="20" Height="20" Margin="5,0,5,0" />
<TextBlock Text="HOME" FontSize="18" FontWeight="Normal" Foreground="Black"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</Button>
<!-- Recipe Selection Button -->
<Button x:Name="RecipeSelTrack" BorderThickness="2" Width="150" Height="60" Click="RecipeSelTrackBtn">
<Grid Width="150" Height="50">
<Polygon x:Name="RecipeSelPolygon" Points="0,0 130,0 150,25 130,50 0,50 20,25"
Stroke="Black" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="RECIPE SEL." FontSize="18" Margin="10,0,0,0"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- Recipe Panel Button -->
<Button x:Name="RecipePanelTrack" BorderThickness="2" Width="170" Height="60" Click="RecipeSelTrackBtn">
<Grid Width="170" Height="50">
<Polygon x:Name="RecipePanelPolygon" Points="0,0 150,0 170,25 150,50 0,50 20,25"
Stroke="Black" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="RECIPE PANEL" FontSize="18" FontWeight="Normal"
Foreground="Black" HorizontalAlignment="Center"
Padding="10,0,0,0"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- Settings Button -->
<Button x:Name="SettingTrack" BorderThickness="2" Width="150" Height="60" Click="SettingTrackBtn">
<Grid Width="150" Height="50">
<Polygon x:Name="SettingPolygon" Points="0,0 130,0 150,25 130,50 0,50 20,25"
Stroke="Black" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="SETTINGS" FontSize="18" FontWeight="Normal"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- Recipe Edit Button -->
<Button x:Name="RecipeEditTrack" BorderThickness="2" Width="170" Height="60">
<Grid Width="170" Height="50">
<Polygon x:Name="RecipeEditPolygon" Points="0,0 150,0 170,25 150,50 0,50 20,25"
Stroke="#A4275D" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="RECIPE EDIT" FontSize="18" FontWeight="Normal"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- Run Interface Button -->
<Button x:Name="RunInterfaceTrack" BorderThickness="2" Width="200" Height="60" IsVisible="False">
<Grid Width="200" Height="50">
<Polygon x:Name="RunInterfacePolygon" Points="0,0 170,0 190,25 170,50 0,50 20,25"
Stroke="#A4275D" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="RUN INTERFACE" FontSize="18" FontWeight="Normal" Margin="0,0,0,0"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- DIAGNOSTICS Button -->
<Button x:Name="DiagnosticsTrack" BorderThickness="2" Width="170" Height="60" IsVisible="False" Click="DiagnosticsBtn">
<Grid Width="170" Height="50">
<Polygon x:Name="DiagnosticsPolygon" Points="0,0 150,0 170,25 150,50 0,50 20,25"
Stroke="#A4275D" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="DIAGNOSTICS" FontSize="20" FontWeight="Normal" Margin="11,0,0,0"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- SOFTWARE Button -->
<Button x:Name="SoftwareTrack" BorderThickness="2" Width="170" Height="60" Margin="0,0,0,0" IsVisible="False" Click="SoftwareBtn">
<Grid Width="170" Height="50">
<Polygon x:Name="SoftwarePolygon" Points="0,0 150,0 170,25 150,50 0,50 20,25"
Stroke="#A4275D" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="SOFTWARE" FontSize="18" FontWeight="Normal" Margin="0,0,0,0"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- ADVANCE SETTINGS Button -->
<Button x:Name="AdvanceSettingsTrack" BorderThickness="2" Width="220" Height="60" Margin="0,0,0,0" IsVisible="False" Click="AdvanceSettingsView">
<Grid Width="220" Height="50">
<Polygon x:Name="AdvanceSettingsPolygon" Points="0,0 200,0 220,25 200,50 0,50 20,25"
Stroke="#A4275D" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="ADVANCE SETTINGS" FontSize="18" FontWeight="Normal" Margin="0,0,0,0"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
<!-- MANUAL CONTROL Button -->
<Button x:Name="ManualControlTrack" BorderThickness="2" Width="200" Height="60" IsVisible="False" Click="ChefManualBtn">
<Grid Width="200" Height="50">
<Polygon x:Name="ManualControlPolygon" Points="0,0 170,0 190,25 170,50 0,50 20,25"
Stroke="#A4275D" StrokeThickness="2" Fill="#E6E6E6"/>
<TextBlock Text="MANUAL CONTROL" FontSize="18" FontWeight="Normal" Margin="0,0,-5,0"
Foreground="Black" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</Button>
</StackPanel>
<StackPanel Grid.Column="2"
HorizontalAlignment="Right" Orientation="Horizontal" Margin="0,0,5,0"
Spacing="0">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="version" VerticalAlignment="Center" FontSize="30" Foreground="Black" Margin="0,0,0,0" IsVisible="True" >V0.6</TextBlock>
<Button x:Name="errorLogoBtn" Background="Transparent" Click="errorLogoClick">
<Image x:Name="errorLogo" IsVisible="False" Tag="Error" Source="/Assets/errorIcon.png" Width="60" Height="60" Stretch="Uniform" Margin="0,0,0,0" ></Image>
</Button>
<Button Background="Transparent" Click="warningLogoClick">
<Image x:Name="warningLogo" IsVisible="False" Tag="Warning" Source="/Assets/warningIcon.png" Height="60" Margin="0,0,0,0" ></Image>
</Button>
<Image x:Name="wifiLogo" IsVisible="False" Tag="Warning" Source="/Assets/wifi.png" Height="60" Margin="0,0,0,0"></Image>
<Image x:Name="nowifiLogo" IsVisible="True" Tag="Warning" Source="/Assets/wifioff.png" Height="60" Margin="0,0,0,0"></Image>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<!-- Recipe Button -->
<Button x:Name="TitleBtn" Background="#A4275D" Foreground="White"
Width="180" Height="50" CornerRadius="10" Margin="10,0,30,0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
>
<Button.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="#A4275D"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style Selector="TextBlock">
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
<TextBlock Text="Product" Foreground="White" FontSize="24" FontWeight="Normal"
HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="Title"></TextBlock>
</Button>
<!-- minimize Button -->
<Button x:Name="minimizeBtn" CornerRadius="10" Width="50" Height="50" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Foreground="White" Background="#666666" FontSize="24" FontWeight="Normal"
Content="-"
IsVisible="False">
<Button.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
<!-- User Button -->
<Button Content="ALL USERS" x:Name="UserName" CornerRadius="10" Width="220" Height="50" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Foreground="White" Background="#666666" FontSize="24" FontWeight="Normal"
>
<Button.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="White"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
</Grid>
</Grid>
<!-- Main Area-->
<ContentControl Padding="0" Margin="0" Grid.Row="1" x:Name="ContentArea" Height="620" Background="#b3b3b3" />
<!--Footer-->
<Grid Grid.Row="2" Margin="0,0,0,0" ColumnDefinitions="Auto,*,Auto" Background="White" x:Name="footer" Height="90" >
<Grid.Styles>
<Style Selector="Button.RecipeStart:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="#008000"></Setter>
</Style>
<Style Selector="Button.PreHeating:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="White"></Setter>
<Setter Property="Background" Value="#d45500"></Setter>
</Style>
</Grid.Styles>
<StackPanel Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Spacing="20" Height="80" Margin="20,0,0,0">
<StackPanel x:Name="footerStartBtn" Orientation="Horizontal" Spacing="20" IsVisible="False">
<!-- START Button -->
<Button Content="START RECIPE"
x:Name="recipeStartBtn" Classes="RecipeStart" Width="320" Height="60" FontSize="40"
Background="#008000" Foreground="White" BorderBrush="#008000"
CornerRadius="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
VerticalAlignment="Center" Padding="0,0,0,0" Margin="0,0,0,0" Click="RecipeStartBtn" >
<Button.Styles>
<!-- Custom Style for Disabled Button -->
<Style Selector="Button:disabled /template/ContentPresenter">
<Setter Property="Background" Value="#E6E6E6"/>
<Setter Property="Foreground" Value="#231F20"/>
</Style>
</Button.Styles>
</Button>
<!--PRE-HEATING Button-->
<Button Content="PRE-HEATING" x:Name="PreHeatingBtn" Classes="PreHeating" Width="320" Height="60" FontSize="40"
Background="#d45500" Foreground="White" BorderBrush="#d45500"
CornerRadius="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
VerticalAlignment="Center" Padding="0,0,0,0" Margin="0,0,0,0"
Click="PreHeatingClick" >
<Button.Styles>
<!-- Custom Style for Disabled Button -->
<Style Selector="Button:disabled /template/ContentPresenter">
<Setter Property="Background" Value="#E6E6E6"/>
<Setter Property="Foreground" Value="#231F20"/>
</Style>
</Button.Styles>
</Button>
</StackPanel>
</StackPanel>
<StackPanel x:Name="adminBtns" IsVisible="False" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Spacing="20" Height="80">
<!-- DIAGNOSTICS Button -->
<StackPanel.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Background" Value="LightGray"></Setter>
<Setter Property="RenderTransform" Value="scale(1.11)"></Setter>
</Style>
</StackPanel.Styles>
<Button Content="DIAGNOSTICS" Width="300" Height="60" FontSize="28" FontWeight="Normal"
Background="LightGray" Foreground="Black" BorderBrush="LightGray"
CornerRadius="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
VerticalAlignment="Center" Margin="40,0,0,0" IsVisible="True" Click="DiagnosticsBtn"/>
<Button Content="SOFTWARE" Width="240" Height="60" FontSize="28" FontWeight="Normal"
Background="LightGray" Foreground="Black" BorderBrush="LightGray"
CornerRadius="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
VerticalAlignment="Center" Margin="40,0,0,0" IsVisible="True" Click="SoftwareBtn"/>
<!-- EDIT Button -->
<!--
<Button Content="EDIT" Click="EditClick" Width="120" Height="50" FontSize="20"
Background="Transparent" Foreground="Gray" BorderBrush="#B0B0B0"
CornerRadius="10" BorderThickness="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
-->
</StackPanel>
<StackPanel x:Name="chefBtns" IsVisible="False" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Spacing="20" Height="80">
<!-- DIAGNOSTICS Button -->
<StackPanel.Styles>
<Style Selector="Button:pointerover /template/ContentPresenter">
<Setter Property="Foreground" Value="Black"></Setter>
<Setter Property="Background" Value="LightGray"></Setter>
<Setter Property="RenderTransform" Value="scale(1.11)"></Setter>
</Style>
</StackPanel.Styles>
<Button Content="MANUAL CONTROL" Width="300" Height="60" FontSize="28" FontWeight="Normal"
Background="LightGray" Foreground="Black" BorderBrush="LightGray"
CornerRadius="10" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
VerticalAlignment="Center" Margin="40,0,0,0" IsVisible="True" Click="ChefManualBtn"/>
</StackPanel>
<Grid Grid.Column="1" x:Name="TextCenter" Margin="" >
<StackPanel VerticalAlignment="Center">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="35" Foreground="Green" x:Name="footerMsg"
IsVisible="True" Padding="0,0,0,0"
TextWrapping="WrapWithOverflow">Ready</TextBlock>
</StackPanel>
</Grid>
<Grid Grid.Column="2" RowDefinitions="*,*" x:Name="footerDateContainer" IsVisible="" Height="55" VerticalAlignment="Center" Margin="0,0,10,0" >
<StackPanel Grid.Row="0" >
<TextBlock VerticalAlignment="Bottom"
FontSize="28" Foreground="Black" HorizontalAlignment="Right"
Margin="0,0,5,0" x:Name="footerTime">12:55 PM</TextBlock>
</StackPanel>
<StackPanel Grid.Row="1" >
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Bottom"
FontSize="28" Foreground="Black" Padding="0,0,0,0" Margin="0,0,0,0" x:Name="footerDate">20/02/2025</TextBlock>
</StackPanel>
</Grid>
</Grid>
<!-- Overlay Background for Popup -->
<Border x:Name="errorPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99"
PointerPressed="OnErrorPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<Grid ColumnDefinitions="Auto,*">
<Grid Grid.Column="0">
<TextBlock x:Name="errorTitel" Text="Error"
FontSize="20"
FontWeight="Bold"
Foreground="Red"
Margin="0,0,40,8" />
</Grid>
<Grid Grid.Column="1">
<Button Background="Red" Foreground="White"
CornerRadius="5"
Width="100"
Height="40"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"
VerticalAlignment="Center"
HorizontalAlignment="Center"
x:Name="resetErrorsBtn"
Click="ResetErrors">Reset Errors</Button>
</Grid>
</Grid>
<StackPanel>
<TextBlock x:Name="errorMsg" Text=""
FontSize="20"
FontWeight="Bold"
Foreground="Black"
Margin="0,0,0,8" />
</StackPanel>
<!-- Button Panel -->
</StackPanel>
</Border>
</Grid>
</Border>
<!-- Overlay Background for Popup -->
<Border x:Name="warningPopupOverlay" Background="#80000000" Grid.RowSpan="3" IsVisible="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ZIndex="99" PointerPressed="OnWarningPopupOverlayPointerPressed">
<!-- Popup User Control -->
<!-- Module for Name Entry -->
<Grid PointerPressed="" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" IsVisible="True">
<Border Background="White" CornerRadius="10" Padding="20" BorderThickness="1" ZIndex="101" BorderBrush="#CCC">
<StackPanel Spacing="15">
<!-- Label for Text Input -->
<!-- Label -->
<TextBlock x:Name="warningTitel" Text="Warning"
FontSize="20"
FontWeight="Bold"
Foreground="Red"
Margin="0,0,0,8" />
<StackPanel>
<TextBlock x:Name="warningMsg" Text=""
FontSize="20"
FontWeight="Bold"
Foreground="Black"
Margin="0,0,0,8" />
</StackPanel>
<!-- Button Panel -->
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</Window>
============================================================
FILE: DaireApplication/Views/MainWindow.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Threading;
using AvaloniaApplication1.ViewModels;
using DaireApplication.DataBase;
using DaireApplication.Loops;
using DaireApplication.ViewModels;
using DynamicData;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using static DaireApplication.ViewModels.Error;
namespace DaireApplication.Views
{
public partial class MainWindow : Window
{
List<byte> buffer = new List<byte>();
public ModBusMaster _modBusMaster = new ModBusMaster();
public MachineTable _machine = new MachineTable();
public ConfigrationTable _config = new ConfigrationTable();
public List<ConfigrationTable> _configrations = new List<ConfigrationTable>();
public Mapping _map = new Mapping();
public ScreeenTable _screeen = new();
public ErrorSettingsTable _error = new();
public List<Mapping> _mapping = new List<Mapping>();
public static bool isOff { get; set; }
const double deadZone = 1.5; // Changeable based on stability needs
bool shouldRunFountain = false;
public readonly SemaphoreSlim _keepSendingLock = new(1, 1);
public SerialPort _port { get; set; }
private static Thread monitorThread;
private static Thread screenThread;
private static Thread touchThread;
private static Thread internetThread;
private static Thread InteractiveUIThread;
private static Thread serialThread;
public bool serialThreadRunning = true;
public bool isRunning = true;
public bool restBoard { get; set; }
public bool sendConfig { get; set; } = true;
public bool reSendHolding { get; set; }
public bool dontResetOutPuts { get; set; }
bool allBitsOn = false;
bool allPedalBitsOn = false;
public int pedalState { get; set; } = -1;
public int pedalStateChanged { get; set; } = -1;
public float recipeHeatingGoal { get; set; }
public float recipeCoolingGoal { get; set; }
public float recipePouringGoal { get; set; }
public string ActiveColor { get; set; } = "#A4275D";
public string PassiveColor { get; set; } = "#666666";
//Pre Heating
public bool isFlashPreHeating { get; set; } = false;
public bool isReadingTemp { get; set; } = true;
public int startPreHeating { get; set; } = -1;
public int writingMaxTemp { get; set; } = -1;
//Mixer Motor
private Timer mixerTimer;
private Timer preMixerTimer;
private static int mixerSeconds = 1;
private static int preMixerSeconds = 1;
public bool setMixerTimerOnce { get; set; } = false;
public bool checkMixerTWT_HWTH { get; set; } = false;
public bool isMixerMotorOn { get; set; } = false;
public int startMixerMotor { get; set; } = -1;
public int startMixerMotorFlashing { get; set; } = -1;
public int sendComMixerMotor { get; set; } = -1;
//Fountain Motor
private Timer fountainTimer;
private Timer fountainPauseTimer;
private Timer noChoiceChoosenTimer;
private static int fountainSeconds = 1;
private static int fountainPauseSeconds = 1;
private static int noChoiceChoosenSeconds = 0;
public bool setFountainTimerOnce { get; set; } = false;
public bool checkFountainTMT_PMT { get; set; } = false;
public bool isFountainMotorOn { get; set; } = false;
public int startFountainMotor { get; set; } = -1;
public int startFountainMotorFlashing { get; set; } = -1;
public int sendComFountainMotor { get; set; } = -1;
public double comTankTemp { get; set; } = 0;
public double comFountainTemp { get; set; } = 0;
public double comPumpTemp { get; set; } = 0;
//MOLD HEATER(off:0,on:1) , VIBRATION(off:0,on:1) , VIB. HEATER(off:0,on:1)
public int moldHeaterMotor { get; set; } = -1;
public int vibrationMotor { get; set; } = -1;
public int vibHeaterMotor { get; set; } = -1;
//Pedal(manual=0,auto=1)
public int pedalMotor { get; set; } = -1;
//Recipe Start
public int startRecipe { get; set; } = 0;
public int sendComTankTemp { get; set; } = -1;
//phase 1 heating
public int Heating { get; set; } = -1;
public int sendComHeating { get; set; } = -1;
public int setHeatingTimerOnce { get; set; } = -1;
public Timer heatingTimer;
public int heatingSeconds { get; set; } = 0;
//phase 2 cooling
public int cooling { get; set; } = -1;
public int sendComCooling { get; set; } = -1;
public int setCoolingTimerOnce { get; set; } = -1;
public Timer coolingTimer;
public int coolingSeconds { get; set; } = 0;
//phase 3 pouring
public int pouring { get; set; } = -1;
public int sendComPouring { get; set; } = -1;
public int setPouringTimerOnce { get; set; } = -1;
public Timer pouringTimer;
public int pouringSeconds { get; set; } = 0;
//start the pumb
public int PumbOn { get; set; } = -1;
public Timer pedalOnTimer;
public Timer pedalOffTimer;
public int pedalOnSeconds { get; set; } = 0;
public int pedalOffSeconds { get; set; } = 0;
// 1 turn off ,0 turn on
public int setPedalTimerOnce { get; set; } = -1;
//Board
public bool resetPort { get; set; } = false;
public bool keepSendingFlag { get; set; } = false;
public DateTime lastActivity = DateTime.Now;
public ScreeenTable screenData = new();
public static List<Error> errors = new();
public bool pause { get; set; }
public bool unPause { get; set; }
public bool isPaused { get; set; }
public bool pauseTimer { get; set; }
public bool pauseTempTracking { get; set; }
public string warningMessage { get; set; }
public HoldingRegister holdingRegister = new HoldingRegister();
public bool turnOnFountainMotor { get; set; }
public bool stopRecipeFlag { get; set; }
public Timer stopMixerTimer;
public int stopMixerSecondes { get; set; }
public Timer stopFountainTimer;
public int stopFountainSecondes { get; set; }
public DateTime _lastPacketSendTime = DateTime.MinValue;
public byte[] inputesResponse = new byte[] { 0xFF };
// Replace isWriting flag with async method
public TaskCompletionSource<bool> _writeCompletionSource = new TaskCompletionSource<bool>();
public Task<bool> WriteToSerialAsync(string caller)
{
_writeCompletionSource = new TaskCompletionSource<bool>();
// Optionally log or store the caller for debugging
Debug.WriteLine($"WriteToSerialAsync called by: {caller}");
return _writeCompletionSource.Task;
}
public void SetWriteComplete(bool success = true)
{
_writeCompletionSource?.TrySetResult(success);
}
public MainWindow()
{
InitializeComponent();
// Hide cursor using unclutter
try
{
var process = new System.Diagnostics.Process();
process.StartInfo.FileName = "unclutter";
process.StartInfo.Arguments = "-idle 0"; // Hide immediately
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
}
catch (Exception ex)
{
Console.WriteLine($"Failed to start unclutter: {ex.Message}");
}
ContentArea.Content = new Home(this);
this.Closing += OnClosingWindow;
_machine = _machine.ReadMachine();
_configrations = _config.ReadConfigrations();
_mapping = _map.ReadMappings();
serialThread = new Thread(() => serialThreadLoop.SendViaSerial(this))
{
IsBackground = true
};
serialThread.Start();
internetThread = new Thread(() => CheckInterNetLoop.CheckInterNet(this))
{
IsBackground = true
};
internetThread.Start();
screenThread = new Thread(() => ScreenLoop.Screen(this))
{
IsBackground = true
};
screenThread.Start();
InteractiveUIThread = new Thread(() => InteractiveUILoop.Flashing(this))
{
IsBackground = true
};
InteractiveUIThread.Start();
touchThread = new Thread(() => TouchLoop.Touch(this))
{
IsBackground = true
};
touchThread.Start();
monitorThread = new Thread(() => MonitorPortsLoop())
{
IsBackground = true,
Priority = ThreadPriority.Highest
};
monitorThread.Start();
}
private async void MonitorPortsLoop()
{
byte[] tankeResponse = new byte[256];
var fountainResponse = new byte[256];
double tankBottomTempValue = -1;
double tankWallTempValue = -1;
double pumpTempValue = -1;
double fountainTempValue = -1;
var tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp");
var tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp");
var pump = _mapping.Find(x => x.Name == "Pump Temp");
var fountain = _mapping.Find(x => x.Name == "Fountain Temp");
static List<bool> ToBinary(int number)
{
return Convert.ToString(number, 2)
.PadLeft(16, '0')
.Reverse()
.Select(c => c == '1')
.ToList();
}
while (true)
{
if (isRunning)
{
Dispatcher.UIThread.Post(() =>
{
footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy");
footerTime.Text = DateTime.Now.ToString("hh:mm tt");
});
screenData = _screeen.ReadScreens()?[0];
try
{
if (!SerialPort.GetPortNames().Contains(screenData.port))
{
if (_port != null && _port.IsOpen)
{
_port.Close();
}
_port = null;
Dispatcher.UIThread.Post(() =>
{
errors.Clear();
footerMsg.Text = "Not Connected:Port Name Not Found";
//Debug.WriteLine("port name not found");
footerMsg.Foreground = Avalonia.Media.Brushes.DarkRed;
footerMsg.IsVisible = true;
});
}
else
{
if (resetPort)
{
Debug.WriteLine("Port reset initiated");
resetAll();
if (_port != null && _port.IsOpen)
{
Debug.WriteLine("Closing existing port");
_port.Close();
}
_port = null;
if (ConnectToSerialPort())
{
Debug.WriteLine("Port reconnected successfully");
Dispatcher.UIThread.Post(() =>
{
//Conntected
footerMsg.Text = "Connected";
footerMsg.IsVisible = true;
sendConfig = true;
});
}
else
{
Debug.WriteLine("Failed to reconnect port");
Dispatcher.UIThread.Post(() =>
{
errors.Clear();
footerMsg.Text = "Not Connected";
footerMsg.IsVisible = true;
});
}
resetPort = false;
Debug.WriteLine("Port reset completed");
}
if (_port == null)
{
// Connect to the found device
if (!ConnectToSerialPort())
{
Dispatcher.UIThread.Post(() =>
{
errors.Clear();
footerMsg.Text = "Not Connected";
});
}
else
{
serialThreadRunning = true;
sendConfig = true;
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Connected";
});
}
}
else
{
try
{
if (!_port.IsOpen)
{
_port.Open();
}
List<int> inputValues = new List<int>();
if (isReadingTemp)
{
if (!_port.IsOpen)
{
_port.Open();
}
// reading inputes
var requstReadingInputs = await _modBusMaster.ReadInputRegisters(0, 18);
if (inputesResponse.Length != 1 && inputesResponse[0] != 0xFF)
{
var result = inputesResponse.Skip(3).Take(inputesResponse.Count() - 5).ToArray();
for (int i = 0; i < result.Length; i = i + 2)
{
inputValues.Add(((result[i] << 8) | result[i + 1]));
}
var brdFlags = ToBinary(inputValues[0]);
var inputes = ToBinary(inputValues[1]);
// Errors
try
{
// Grid Vac
if (inputValues[2] > 220 * 1.1 || inputValues[3] > 220 * 1.1 || inputValues[4] > 220 * 1.1)
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACHigh) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.GridVACHigh
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACHigh) != null)
{
errors.First(x => x.Condition == Error.GridCondition.GridVACHigh).isDeleted = true;
}
}
if (inputValues[2] < 220 * 0.9 || inputValues[3] < 220 * 0.9 || inputValues[4] < 220 * 0.9)
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACLow) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.GridVACLow
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACLow) != null)
{
errors.First(x => x.Condition == Error.GridCondition.GridVACLow).isDeleted = true;
}
}
//// Grid Freq
_error = _error.ReadErrorSettings()[0];
if (inputValues[17] > (_error.gridFreq * 10) * 1.1)
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyHigh) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.GridFrequencyHigh
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyHigh) != null)
{
errors.First(x => x.Condition == Error.GridCondition.GridFrequencyHigh).isDeleted = true;
}
}
if (inputValues[17] < (_error.gridFreq * 10) * 0.9)
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyLow) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.GridFrequencyLow
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyLow) != null)
{
errors.First(x => x.Condition == Error.GridCondition.GridFrequencyLow).isDeleted = true;
}
}
//// Ext Power
if (brdFlags[3])
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoExternalPower) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.NoExternalPower
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoExternalPower) != null)
{
errors.First(x => x.Condition == Error.GridCondition.NoExternalPower).isDeleted = true;
}
}
//// missing Phase
if (brdFlags[5] && _error.ReadErrorSettings()[0].phaseNumber == 3)
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.MissingPhase) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.MissingPhase
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.MissingPhase) != null)
{
errors.First(x => x.Condition == Error.GridCondition.MissingPhase).isDeleted = true;
}
}
//// Phase sequence
if (brdFlags[4] && _error.ReadErrorSettings()[0].phaseNumber == 3)
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.PhaseSequence) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.PhaseSequence
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.PhaseSequence) != null)
{
errors.First(x => x.Condition == Error.GridCondition.PhaseSequence).isDeleted = true;
}
}
//com port1
if (brdFlags[1])
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort1) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.ComPort1
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort1) != null)
{
errors.First(x => x.Condition == Error.GridCondition.ComPort1).isDeleted = true;
}
}
//com port2
if (brdFlags[2])
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort2) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.ComPort2
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort2) != null)
{
errors.First(x => x.Condition == Error.GridCondition.ComPort2).isDeleted = true;
}
}
//hi curr neut
if (brdFlags[6])
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrNeut) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.HiCurrNeut
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrNeut) != null)
{
errors.First(x => x.Condition == Error.GridCondition.HiCurrNeut).isDeleted = true;
}
}
//hi curr mot1
if (brdFlags[7])
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot1) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.HiCurrMot1
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot1) != null)
{
errors.First(x => x.Condition == Error.GridCondition.HiCurrMot1).isDeleted = true;
}
}
//hi curr mot2
if (brdFlags[8])
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot2) == null)
{
errors.Add(new Error
{
errorDate = DateTime.Now,
Condition = Error.GridCondition.HiCurrMot2
});
}
}
else
{
if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot2) != null)
{
errors.First(x => x.Condition == Error.GridCondition.HiCurrMot2).isDeleted = true;
}
}
}
catch (Exception)
{
}
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Diagnostics diagnostics)
{
//Board Falgs
foreach (var item in diagnostics.flagRectangles)
{
if (brdFlags[int.Parse(item.Tag.ToString())])
{
item.Fill = Brush.Parse(diagnostics.RedColor);
}
else
{
item.Fill = Brush.Parse(diagnostics.GrayColor);
}
}
//power Inputes
diagnostics.ph1.Text = inputValues[2].ToString();
diagnostics.ph2.Text = inputValues[3].ToString();
diagnostics.ph3.Text = inputValues[4].ToString();
diagnostics.i_nut.Text = (inputValues[5] / 10.0).ToString("0.0");
diagnostics.gridFreq.Text = (inputValues[17] / 10.0).ToString("0.0");
// Inputes
foreach (var item in diagnostics.InputesElements.OfType<Grid>().ToList())
{
var text = item.Children[0] as TextBlock;
var border = item.Children[1] as Border;
if (inputes[int.Parse(item.Tag.ToString())])
{
text.Text = "ACTIVE";
border.Background = Brush.Parse(diagnostics.PinkColor);
diagnostics.InputesElements.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor);
}
else
{
text.Text = "PASSIVE";
border.Background = Brush.Parse(diagnostics.GrayColor);
diagnostics.InputesElements.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor);
}
}
//Analog
diagnostics.an1.Text = inputValues[12].ToString();
diagnostics.an2.Text = inputValues[13].ToString();
//Temp
diagnostics.t1.Text = ((short)inputValues[8] / 10f).ToString("0.0");
diagnostics.t2.Text = ((short)inputValues[9] / 10f).ToString("0.0");
diagnostics.t3.Text = ((short)inputValues[10] / 10f).ToString("0.0");
diagnostics.t4.Text = ((short)inputValues[11] / 10f).ToString("0.0");
//InternalTemp
diagnostics.internalTemp.Text = (inputValues[15] / 10.0).ToString("0.0");
diagnostics.hsTemp.Text = (inputValues[14] / 10.0).ToString("0.0");
if (inputValues[16] > 40)
{
diagnostics.extPowerLed.Fill = Brush.Parse(diagnostics.RedColor);
}
else
{
diagnostics.extPowerLed.Fill = Brush.Parse(diagnostics.GrayColor);
}
diagnostics.ExtPwr.Text = (inputValues[16] / 10.0).ToString("0.0");
}
if (ContentArea.Content is Settings settings)
{
if (settings.pedalStateTxt.Text != "AUTO")
{
var pedal = _mapping.Find(x => x.Name.ToLower() == "pedal");
ushort registerValue = (ushort)inputValues[1];
if (allBitsOn != pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0))
{
allBitsOn = pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0);
}
if (!allBitsOn)
{
settings.pedalUnderLine.Fill = Brush.Parse(settings.PassiveColor);
}
else
{
settings.pedalUnderLine.Fill = Brush.Parse(settings.ActiveColor);
}
}
if (startFountainMotorFlashing != 1)
{
//fountain
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (allBitsOn != fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0))
{
allBitsOn = fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0);
}
var fountainLable = settings.FountainSP.Children[1] as Avalonia.Controls.Label;
var fontainRectangel = settings.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle;
if (!allBitsOn)
{
fountainLable.Content = "OFF";
fountainLable.Foreground = Brush.Parse("#ff231f20");
fontainRectangel.Fill = Brush.Parse(PassiveColor);
//isFountainMotorOn = false;
}
else
{
fountainLable.Content = "ON";
fountainLable.Foreground = Brush.Parse("#ff231f20");
fontainRectangel.Fill = Brush.Parse(ActiveColor);
//isFountainMotorOn = true;
}
}
if (startMixerMotorFlashing != 1)
{
//mixer
var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower());
if (allBitsOn != mixer.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0))
{
allBitsOn = mixer.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0);
}
var mixerLable = settings.MixerSP.Children[1] as Avalonia.Controls.Label;
var mixerRectangel = settings.MixerSP.Children[2] as
Avalonia.Controls.Shapes.Rectangle;
if (!allBitsOn)
{
mixerLable.Content = "OFF";
mixerLable.Foreground = Brush.Parse("#ff231f20");
mixerRectangel.Fill = Brush.Parse(PassiveColor);
//isMixerMotorOn = false;
}
else
{
mixerLable.Content = "ON";
mixerLable.Foreground = Brush.Parse("#ff231f20");
mixerRectangel.Fill = Brush.Parse(ActiveColor);
//isMixerMotorOn = true;
}
}
}
if (ContentArea.Content is ManualControl manual)
{
manual.pumbRealTemp.Text = comPumpTemp.ToString("0.0");
manual.ChocolateRealTemp.Text = comFountainTemp.ToString("0.0");
manual.tankWallRealTemp.Text = tankWallTempValue.ToString("0.0");
manual.pumbRealTemp.Text = comTankTemp.ToString("0.0");
}
});
_mapping = _map.ReadMappings();
//reading Tank Bottom
tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp");
if (tankBottom != null)
{
if (tankBottom.BitNumbers.Count > 0)
{
tankBottomTempValue = 0;
foreach (var item in tankBottom.BitNumbers)
{
tankBottomTempValue += ((short)inputValues[item] / 10f);
}
tankBottomTempValue /= tankBottom.BitNumbers.Count;
tankBottomTempValue = Math.Round(tankBottomTempValue, 1);
}
}
//reading Tank Wall
tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp");
if (tankWall != null)
{
if (tankWall.BitNumbers.Count > 0)
{
tankWallTempValue = 0;
foreach (var item in tankWall.BitNumbers)
{
tankWallTempValue += ((short)inputValues[item] / 10f);
}
tankWallTempValue /= tankWall.BitNumbers.Count;
tankWallTempValue = Math.Round(tankWallTempValue, 1);
}
}
//reading Pump
pump = _mapping.Find(x => x.Name == "Pump Temp");
if (pump != null)
{
if (pump.BitNumbers.Count > 0)
{
pumpTempValue = 0;
foreach (var item in pump.BitNumbers)
{
pumpTempValue += ((short)inputValues[item] / 10f);
}
pumpTempValue /= pump.BitNumbers.Count;
pumpTempValue = Math.Round(pumpTempValue, 1);
}
}
//reading Fountain
fountain = _mapping.Find(x => x.Name == "Fountain Temp");
if (fountain != null)
{
if (fountain.BitNumbers.Count > 0)
{
fountainTempValue = 0;
foreach (var item in fountain.BitNumbers)
{
fountainTempValue += ((short)inputValues[item] / 10f);
}
fountainTempValue /= fountain.BitNumbers.Count;
fountainTempValue = Math.Round(fountainTempValue, 1);
}
}
Dispatcher.UIThread.Post(() =>
{
if (tankBottomTempValue == -1 && tankWallTempValue == -1)
{
if (ContentArea.Content is Settings)
{
footerMsg.Text = "No Tank Data To Read";
tankBottomTempValue = 0;
tankWallTempValue = 0;
}
}
else
{
//comTankTemp = tankBottomTempValue < tankWallTempValue ? tankBottomTempValue : tankWallTempValue;
comTankTemp = tankBottomTempValue;
comTankTemp = comTankTemp == -1 ? 0 : comTankTemp;
}
if (pumpTempValue == -1)
{
if (ContentArea.Content is Settings)
{
footerMsg.Text = "No Pump Data To Read";
pumpTempValue = 0;
}
}
else
{
comPumpTemp = pumpTempValue;
}
if (fountainTempValue == -1)
{
if (ContentArea.Content is Settings)
{
footerMsg.Text = "No Chocolate Data To Read";
fountainTempValue = 0;
}
}
else
{
comFountainTemp = fountainTempValue;
}
if (ContentArea.Content is Settings result)
{
if (result.TankTempValue.Content?.ToString() != comTankTemp.ToString() || result.FountainTempValue.Content?.ToString() != comFountainTemp.ToString())
{
result.TankTempValue.Content = (comTankTemp).ToString("0.0");
result.FountainTempValue.Content = (comFountainTemp).ToString("0.0");
}
}
//if (comTankTemp >= _machine.TankMaxHeat && comFountainTemp >= _machine.PumbMaxHeat)
//{
// if (preMixerTimer==null)
// {
// preMixerTimer = new Timer(PreMixerTimer, null, 0, 1000);
// }
// mixerSeconds++;
//}
//else
//{
// if (preMixerTimer != null)
// {
// preMixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
// preMixerTimer = null;
// }
//}
}
);
}
//read mot val
if (inputValues.Count != 0)
{
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Diagnostics diagnostics)
{
diagnostics.curr1.Text = (inputValues[6] / 10.0).ToString("0.0");
diagnostics.curr2.Text = (inputValues[7] / 10.0).ToString("0.0");
}
});
}
}
//Pre Heating
if (startPreHeating == 1)
{
List<int> setTempValues = new List<int>();
setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]);
if (writingMaxTemp == 1)
{
tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp");
if (tankBottom != null)
{
if (tankBottom.BitNumbers.Count > 0)
{
foreach (var item in tankBottom.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10;
}
}
}
tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp");
if (tankWall != null)
{
if (tankWall.BitNumbers.Count > 0)
{
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10;
}
}
}
pump = _mapping.Find(x => x.Name == "Pump Temp");
if (pump != null)
{
if (pump.BitNumbers.Count > 0)
{
foreach (var item in pump.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.PumbMaxHeat * 10;
}
}
}
fountain = _mapping.Find(x => x.Name == "Fountain Temp");
if (fountain != null)
{
if (fountain.BitNumbers.Count > 0)
{
foreach (var item in fountain.BitNumbers)
{
setTempValues[item - 8] = -10000;
}
}
}
holdingRegister.setTemp1 = setTempValues[0];
holdingRegister.setTemp2 = setTempValues[1];
holdingRegister.setTemp3 = setTempValues[2];
holdingRegister.setTemp4 = setTempValues[3];
await WriteToSerialAsync("PreHeating");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
result.recipeSettings.IsEnabled = false;
isFlashPreHeating = true;
footerMsg.Text = "Pre-Heating Active";
}
});
writingMaxTemp = -1;
}
}
if (startPreHeating == 0)
{
List<int> setTempValues = new List<int>();
setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]);
if (writingMaxTemp == 0)
{
tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp");
if (tankBottom != null)
{
if (tankBottom.BitNumbers.Count > 0)
{
foreach (var item in tankBottom.BitNumbers)
{
setTempValues[item - 8] = -10000;
}
}
}
tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp");
if (tankWall != null)
{
if (tankWall.BitNumbers.Count > 0)
{
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = -10000;
}
}
}
pump = _mapping.Find(x => x.Name == "Pump Temp");
if (pump != null)
{
if (pump.BitNumbers.Count > 0)
{
foreach (var item in pump.BitNumbers)
{
setTempValues[item - 8] = -10000;
}
}
}
fountain = _mapping.Find(x => x.Name == "Fountain Temp");
if (fountain != null)
{
if (fountain.BitNumbers.Count > 0)
{
foreach (var item in fountain.BitNumbers)
{
setTempValues[item - 8] = -10000;
}
}
}
holdingRegister.setTemp1 = setTempValues[0];
holdingRegister.setTemp2 = setTempValues[1];
holdingRegister.setTemp3 = setTempValues[2];
holdingRegister.setTemp4 = setTempValues[3];
await WriteToSerialAsync("PreHeating");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
result.recipeSettings.IsEnabled = true;
if (!stopRecipeFlag)
{
footerMsg.Text = "Pre-Heating Stopped";
}
}
});
writingMaxTemp = -1;
}
}
//Mixer Motor
//Mixer Motorf
if (checkMixerTWT_HWTH)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
recipeHeatingGoal = result._recipeTable.HeatingGoal;
recipeCoolingGoal = result._recipeTable.CoolingGoal;
recipePouringGoal = result._recipeTable.PouringGoal;
}
if ((comTankTemp >= _machine.TankMaxHeat - screenData.warningLimit) && (comTankTemp <= _machine.TankMaxHeat + screenData.warningLimit))
{
if (startMixerMotor != 1)
{
if (mixerTimer == null)
{
if (mixerSeconds == 1)
{
mixerSeconds = _machine.MixerDelay;
}
mixerTimer = new Timer(MixerTimer, null, 0, 1000);
//setMixerTimerOnce = false;
}
}
}
else if (comTankTemp <= recipeCoolingGoal - 3 && startMixerMotor == 1)
{
if (startMixerMotor != 0)
{
if (stopMixerTimer == null)
{
stopMixerSecondes = 5;
stopMixerTimer = new Timer(StopMixerTimer, null, 0, 1000);
}
}
startMixerMotorFlashing = 1;
}
else if (startMixerMotor != 1)
{
if (startMixerMotor != 0)
{
sendComMixerMotor = 0;
}
startMixerMotorFlashing = 1;
}
});
}
if (!checkMixerTWT_HWTH)
{
if (sendComMixerMotor == 0 && startMixerMotorFlashing == 0)
{
startMixerMotor = -1;
var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower());
if (mixer != null)
{
if (mixer.BitNumbers.Count > 0)
{
//turn the motor off and make the button stable
foreach (var bit in mixer.BitNumbers)
{
holdingRegister.motor &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("Mixer Off due Clicking");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label;
var motorRectangel = result.MixerSP.Children[2] as
Avalonia.Controls.Shapes.Rectangle;
motorLable.Content = "OFF";
motorLable.Foreground = Brush.Parse("#ff231f20");
motorRectangel.Fill = Brush.Parse(PassiveColor);
if (startRecipe != 1 && !stopRecipeFlag)
{
footerMsg.Text = "Mixer is OFF";
}
}
});
sendComMixerMotor = -1;
startMixerMotorFlashing = -1;
}
}
}
}
if (startMixerMotorFlashing == 1)
{
if (sendComMixerMotor == 0)
{
//turn the motor off
startMixerMotor = 0;
var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower());
if (mixer != null)
{
if (mixer.BitNumbers.Count > 0)
{
//turn the motor off and make the button stable
foreach (var bit in mixer.BitNumbers)
{
holdingRegister.motor &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("Mixer Off due to drop in temp");
Dispatcher.UIThread.Post(() =>
{
if (startRecipe != 1)
{
footerMsg.Text = "waiting for tank target temperature";
}
});
sendComMixerMotor = -1;
}
}
}
}
if (startMixerMotorFlashing == 0 && sendComMixerMotor == 1 && !isPaused)
{
startMixerMotor = 1;
//turn the motor on and make the button stable
var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower());
if (mixer != null)
{
if (mixer.BitNumbers.Count > 0)
{
foreach (var bit in mixer.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
await WriteToSerialAsync("Mixer On");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label;
var motorRectangel = result.MixerSP.Children[2] as
Avalonia.Controls.Shapes.Rectangle;
motorLable.Content = "ON";
motorLable.Foreground = Brush.Parse("#ff231f20");
motorRectangel.Fill = Brush.Parse(ActiveColor);
if (startRecipe != 1)
{
footerMsg.Text = "Temperature is OK,Mixer is on";
}
//if (comTankTemp < result._recipeTable.PouringGoal ||
// comFountainTemp < result._recipeTable.PouringGoal)
//{
// mixerSeconds = 1;
// //checkTMT_PMT = true;
// setMixerTimerOnce = true;
//}
//else
//{
// //checkTMT_PMT = true;
// setMixerTimerOnce = true;
//}
}
});
startMixerMotorFlashing = -1;
sendComMixerMotor = -1;
}
}
}
//Fountain Motor
if (checkFountainTMT_PMT)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
recipeHeatingGoal = result._recipeTable.HeatingGoal;
recipeCoolingGoal = result._recipeTable.CoolingGoal;
recipePouringGoal = result._recipeTable.PouringGoal;
}
if ((comPumpTemp >= _machine.PumbMaxHeat - screenData.warningLimit) && (comPumpTemp <= _machine.PumbMaxHeat + screenData.warningLimit)) // check the temp and make it stop only if it below cooling temp - 3 degrees
{
if (startFountainMotor != 1)
{
if (fountainTimer == null)
{
if (fountainSeconds == 1)
{
fountainSeconds = _machine.PumbDelay;
}
fountainTimer = new Timer(FountainTimer, null, 0, 1000);
//setFountainTimerOnce = false;
}
}
}
else if (comPumpTemp <= recipeCoolingGoal - 3 && startFountainMotor == 1)
{
if (startFountainMotor != 0)
{
if (stopFountainTimer == null)
{
stopFountainSecondes = 5;
stopFountainTimer = new Timer(StopFountainTimer, null, 0, 1000);
}
}
startFountainMotorFlashing = 1;
}
else if (startFountainMotor != 1)
{
if (startFountainMotor != 0)
{
sendComFountainMotor = 0;
}
startFountainMotorFlashing = 1;
}
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
if (startFountainMotor != 1 && fountainTimer == null)
{
if (!result.fountainDelayCounter.Text.Equals(comPumpTemp.ToString("0.0")))
{
result.fountainDelayTxt.Text = "Current Temp:";
result.fountainDelayCounter.Text = comPumpTemp.ToString("0.0");
result.fountainTargetTxt.Text = "Target Temp:";
result.fountainTagetTemp.Text = _machine.PumbMaxHeat.ToString("0.0");
result.fountainDelayTxt.IsVisible = true;
result.fountainDelayCounter.IsVisible = true;
result.fountainTargetTxt.IsVisible = true;
result.fountainTagetTemp.IsVisible = true;
}
}
}
});
});
}
if (!checkFountainTMT_PMT)
{
if (sendComFountainMotor == 0 && startFountainMotorFlashing == 0)
{
startFountainMotor = -1;
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
//turn the motor off and make the button stable
foreach (var bit in fount.BitNumbers)
{
holdingRegister.motor &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("Fountain Off due to click");
//waitting for 10 sec before pause
if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null
))
{
fountainPauseSeconds = 10;
fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000);
}
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
result.fountainDelayCounter.Text = "-1";
var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label;
var fontainRectangel = result.FountainSP.Children[2] as
Avalonia.Controls.Shapes.Rectangle;
fountainLable.Content = "OFF";
fountainLable.Foreground = Brush.Parse("#ff231f20");
fontainRectangel.Fill = Brush.Parse(PassiveColor);
if (startRecipe != 1 && !stopRecipeFlag)
{
footerMsg.Text = "Chocolate is OFF";
}
stopRecipeFlag = false;
}
});
sendComFountainMotor = -1;
startFountainMotorFlashing = -1;
}
}
}
}
if (startFountainMotorFlashing == 1)
{
if (sendComFountainMotor == 0)
{
startFountainMotor = 0;
//turn the motor off
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
foreach (var bit in fount.BitNumbers)
{
holdingRegister.motor &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("Fountain Off due to drop in temp");
//pause the recipe if it started
//waitting for 10 sec before pause
if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null
))
{
fountainPauseSeconds = 10;
fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000);
}
Dispatcher.UIThread.Post(() =>
{
if (startRecipe == 1 && (Heating == 1 || cooling == 1 || pouring == 1))
{
//footerMsg.Text = "Recipe Paused... waiting for target temperature";
}
else if (startRecipe != 1)
{
footerMsg.Text = "waiting for pump target temperature";
}
});
//checkTMT_PMT = true;
sendComFountainMotor = -1;
}
}
}
}
if (startFountainMotorFlashing == 0 && sendComFountainMotor == 1 && errors.Count == 0 && !isPaused)
{
startFountainMotor = 1;
//turn the motor on and make the button stable
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
foreach (var bit in fount.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
await WriteToSerialAsync("Fountain On");
if (isPaused)
{
unPause = true;
}
//if (startRecipe == 1 && (Heating == 10 || cooling == 10 || pouring == 10))
//{
// if (Heating == 10)
// {
// Heating = 1;
// sendComHeating = 1;
// }
// else if (cooling == 10)
// {
// cooling = 1;
// sendComCooling = 1;
// }
// else if (pouring == 10)
// {
// pouring = 1;
// sendComPouring = 1;
// }
//}
if (fountainPauseTimer != null)
{
fountainPauseTimer = null;
fountainPauseSeconds = 10;
}
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Settings result)
{
var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label;
var fountainRectangel = result.FountainSP.Children[2] as
Avalonia.Controls.Shapes.Rectangle;
fountainLable.Content = "ON";
fountainLable.Foreground = Brush.Parse("#ff231f20");
fountainRectangel.Fill = Brush.Parse(ActiveColor);
if (startRecipe == 1 && (Heating == 1 || cooling == 1 || pouring == 1))
{
if (Heating == 1)
{
footerMsg.Text = "Heating phase";
}
else if (cooling == 1)
{
footerMsg.Text = "Cooling phase";
}
else if (pouring == 1)
{
footerMsg.Text = "Prepare for pouring";
}
}
else if (startRecipe != 1)
{
footerMsg.Text = "Temperature is OK,Chocolate is on";
}
//if (comTankTemp < result._recipeTable.PouringGoal ||
// comFountainTemp < result._recipeTable.PouringGoal)
//{
// fountainSeconds = 1;
// setFountainTimerOnce = true;
//}
//else
//{
// setFountainTimerOnce = true;
//}
}
});
startFountainMotorFlashing = -1;
sendComFountainMotor = -1;
}
}
}
if (moldHeaterMotor == 0) // off MOLD HEATER
{
var moldHeater = _mapping.Find(x => x.Name == "Mold Heater");
if (moldHeater != null)
{
if (moldHeater.BitNumbers.Count > 0)
{
foreach (var bit in moldHeater.BitNumbers)
{
holdingRegister.lvOut &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("MoldHeater");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var StackPanel = result.moldHeaterBtn.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var targetLable = Label[1] as Label;
targetLable.Content = "OFF";
underLine.Fill = Brush.Parse("#666666");
}
else if (ContentArea.Content is ManualControl manual)
{
manual.MoldHeaterStatus.Text = "OFF";
manual.MoldHeaterUnderline.Fill = Brush.Parse("#666666");
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Programming Team";
});
}
moldHeaterMotor = -1;
}
else if (moldHeaterMotor == 1) // on MOLD HEATER
{
var moldHeater = _mapping.Find(x => x.Name == "Mold Heater");
if (moldHeater != null)
{
if (moldHeater.BitNumbers.Count > 0)
{
foreach (var bit in moldHeater.BitNumbers)
{
holdingRegister.lvOut |= (ushort)(1 << bit);
}
await WriteToSerialAsync("MoldHeater");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var StackPanel = result.moldHeaterBtn.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var targetLable = Label[1] as Label;
targetLable.Content = "ON";
underLine.Fill = Brush.Parse("#A4275D");
}
else if (ContentArea.Content is ManualControl manual)
{
manual.MoldHeaterStatus.Text = "ON";
manual.MoldHeaterUnderline.Fill = Brush.Parse("#A4275D");
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Programming Team";
});
}
moldHeaterMotor = -1;
}
if (vibrationMotor == 0) // off VIBRATION
{
var vibrator = _mapping.Find(x => x.Name == "Vibrator");
if (vibrator != null)
{
if (vibrator.BitNumbers.Count > 0)
{
foreach (var bit in vibrator.BitNumbers)
{
holdingRegister.hvOut &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("Vibrator");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var StackPanel = result.vibrationBtn.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var targetLable = Label[1] as Label;
targetLable.Content = "OFF";
underLine.Fill = Brush.Parse("#666666");
}
else if (ContentArea.Content is ManualControl manual)
{
manual.VibrationStatus.Text = "OFF";
manual.VibrationUnderline.Fill = Brush.Parse("#666666");
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Programming Team";
});
}
vibrationMotor = -1;
}
else if (vibrationMotor == 1) // on VIBRATION
{
var vibrator = _mapping.Find(x => x.Name == "Vibrator");
if (vibrator != null)
{
if (vibrator.BitNumbers.Count > 0)
{
foreach (var bit in vibrator.BitNumbers)
{
holdingRegister.hvOut |= (ushort)(1 << bit);
}
await WriteToSerialAsync("Vibrator");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var StackPanel = result.vibrationBtn.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var targetLable = Label[1] as Label;
targetLable.Content = "ON";
underLine.Fill = Brush.Parse("#A4275D");
}
else if (ContentArea.Content is ManualControl manual)
{
manual.VibrationStatus.Text = "ON";
manual.VibrationUnderline.Fill = Brush.Parse("#A4275D");
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Programming Team";
});
}
vibrationMotor = -1;
}
if (vibHeaterMotor == 0) // off VIB. HEATER
{
var vibHeater = _mapping.Find(x => x.Name == "Vibrator Heater");
if (vibHeater != null)
{
if (vibHeater.BitNumbers.Count > 0)
{
foreach (var bit in vibHeater.BitNumbers)
{
holdingRegister.lvOut &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("VibratorHeater");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var StackPanel = result.vibHeaterBtn.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var targetLable = Label[1] as Label;
targetLable.Content = "OFF";
underLine.Fill = Brush.Parse("#666666");
}
else if (ContentArea.Content is ManualControl manual)
{
manual.VibHeaterStatus.Text = "OFF";
manual.VibHeaterUnderline.Fill = Brush.Parse("#666666");
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Programming Team";
});
}
vibHeaterMotor = -1;
}
else if (vibHeaterMotor == 1) // on VIB. HEATER
{
var vibHeater = _mapping.Find(x => x.Name == "Vibrator Heater");
if (vibHeater != null)
{
if (vibHeater.BitNumbers.Count > 0)
{
foreach (var bit in vibHeater.BitNumbers)
{
holdingRegister.lvOut |= (ushort)(1 << bit);
}
await WriteToSerialAsync("VibratorHeater");
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
var StackPanel = result.vibHeaterBtn.Content as StackPanel;
var Label = StackPanel.Children;
var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle;
var targetLable = Label[1] as Label;
targetLable.Content = "ON";
underLine.Fill = Brush.Parse("#A4275D");
}
else if (ContentArea.Content is ManualControl manual)
{
manual.VibHeaterStatus.Text = "ON";
manual.VibHeaterUnderline.Fill = Brush.Parse("#A4275D");
}
});
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Programming Team";
});
}
vibHeaterMotor = -1;
}
//Start Recipe
if (startRecipe == 1)
{
var tankBtm = _mapping.Find(x => x.Name.ToLower() == "Tank Bottom Temp".ToLower());
tankWall = _mapping.Find(x => x.Name.ToLower() == "Tank Wall Temp".ToLower());
var pumb = _mapping.Find(x => x.Name.ToLower() == "Pump Temp".ToLower());
var fount = _mapping.Find(x => x.Name.ToLower() == "Fountain Temp".ToLower());
var fountainMotor = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
var mixerMotor = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower());
if (tankBtm != null && tankWall != null && pumb != null && fount != null)
{
if (tankBtm.BitNumbers.Count > 0 && tankWall.BitNumbers.Count > 0 && pumb.BitNumbers.Count > 0 && fount.BitNumbers.Count > 0)
{
List<int> setTempValues = new List<int>();
setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]);
byte[] response = new byte[] { 0xFF };
var isFountOn = false;
var isMixerOn = false;
if (isFountOn != fountainMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0))
{
isFountOn = fountainMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0);
}
if (isMixerOn != mixerMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0))
{
isMixerOn = mixerMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0);
}
if (isFountOn && isMixerOn) // both motores are on
{
if ((comFountainTemp * 10 >= (recipeHeatingGoal * 10)) && (cooling != 1 && pouring != 1))
{
if (heatingTimer == null)
{
heatingTimer = new Timer(HeatingTimer, null, 0, 1000);
heatingSeconds = _machine.HeatingDelay;
}
}
else if ((Heating != 1) && (cooling != 1 || cooling != 10) && (pouring != 1 || pouring != 10))
{
sendComTankTemp = 1;
Heating = 1;
sendComHeating = 1;
setHeatingTimerOnce = 1;
}
}
//if (comPumpTemp>=_machine.PumbMaxHeat)
//{
// //start timer
// if (fountainTimer==null)
// {
// if (fountainSeconds == 1)
// {
// fountainSeconds = _machine.PumbDelay;
// }
// fountainTimer = new Timer(FountainTimer, null, 0, 1000);
// }
// if (turnOnFountainMotor)
// {
// fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
// if (fount != null)
// {
// if (fount.BitNumbers.Count > 0)
// {
// foreach (var bit in fount.BitNumbers)
// {
// holdingRegister.motor |= (ushort)(1 << bit);
// }
// isWriting = true;
// }
// }
// turnOnFountainMotor = false;
// }
//}
//else
//{
// startFountainMotorFlashing = 1;
//}
if (sendComTankTemp == 1)
{
sendComTankTemp = -1;
}
if (pause)
{
isPaused = true;
if (Heating == 1)
{
Heating = 10;
}
else if (cooling == 1)
{
cooling = 10;
}
else if (pouring == 1)
{
pouring = 10;
}
//PumbOn = -1;
if (tankBtm != null)
{
if (tankBtm.BitNumbers.Count > 0)
{
foreach (var item in tankBtm.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10;
}
}
}
if (tankWall != null)
{
if (tankWall.BitNumbers.Count > 0)
{
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10;
}
}
}
if (pumb != null)
{
if (pumb.BitNumbers.Count > 0)
{
foreach (var item in pumb.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.PumbMaxHeat * 10;
}
}
}
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
foreach (var item in fount.BitNumbers)
{
setTempValues[item - 8] = -10000;
}
}
}
holdingRegister.setTemp1 = setTempValues[0];
holdingRegister.setTemp2 = setTempValues[1];
holdingRegister.setTemp3 = setTempValues[2];
holdingRegister.setTemp4 = setTempValues[3];
holdingRegister.motor = 0;
await WriteToSerialAsync("RecipePause");
startMixerMotor = 0;
startFountainMotor = 0;
if (heatingTimer != null)
{
heatingTimer.Change(Timeout.Infinite, Timeout.Infinite);
heatingSeconds = _machine.HeatingDelay;
heatingTimer = null;
}
if (coolingTimer != null)
{
coolingTimer.Change(Timeout.Infinite, Timeout.Infinite);
coolingSeconds = _machine.CoolingDelay;
coolingTimer = null;
}
if (pouringTimer != null)
{
pouringTimer.Change(Timeout.Infinite, Timeout.Infinite);
pouringSeconds = _machine.PouringDelay;
pouringTimer = null;
}
if (pedalOffTimer != null)
{
pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOffSeconds = 0;
}
if (pedalOnTimer != null)
{
pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOnSeconds = 0;
}
if (fountainPauseTimer != null)
{
fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainPauseSeconds = 10;
fountainPauseTimer = null;
}
if (fountainTimer != null)
{
fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainTimer = null;
}
if (mixerTimer != null)
{
mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
mixerTimer = null;
}
Dispatcher.UIThread.Post(async () =>
{
footerMsg.Text = "Recipe Paused";
});
pause = false;
}
else if (unPause)
{
isPaused = false;
if (Heating == 10)
{
Heating = 1;
sendComHeating = 1;
}
else if (cooling == 10)
{
cooling = 1;
sendComCooling = 1;
}
else if (pouring == 10)
{
pouring = 1;
sendComPouring = 1;
}
PumbOn = 1;
Dispatcher.UIThread.Post(async () =>
{
footerMsg.Text = "Recipe Continued";
});
unPause = false;
}
if (Heating == 1)
{
if (errors.Count > 0)
{
if ((DateTime.Now - errors.Min(x => x.errorDate)).TotalSeconds >= 3.5)
{
if (!isPaused)
{
pause = true;
}
}
}
else
{
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Settings result)
{
if (comFountainTemp * 10 <= (result._recipeTable?.HeatingGoal * 10) + screenData.warningLimit &&
comFountainTemp * 10 >= (result._recipeTable?.HeatingGoal * 10) - screenData.warningLimit)
{
if (setHeatingTimerOnce == 1)
{
heatingTimer = new Timer(HeatingTimer, null, 0, 1000);
heatingSeconds = _machine.HeatingDelay;
setHeatingTimerOnce = -1;
}
}
else if (sendComHeating == 1)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
recipeHeatingGoal = result._recipeTable.HeatingGoal;
recipeCoolingGoal = result._recipeTable.CoolingGoal;
recipePouringGoal = result._recipeTable.PouringGoal;
}
});
foreach (var item in tankBtm.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat;
}
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat;
}
foreach (var item in pumb.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.PumbMaxHeat;
}
foreach (var item in fount.BitNumbers)
{
setTempValues[item - 8] = (int)recipeHeatingGoal;
}
holdingRegister.setTemp1 = setTempValues[0] * 10;
holdingRegister.setTemp2 = setTempValues[1] * 10;
holdingRegister.setTemp3 = setTempValues[2] * 10;
holdingRegister.setTemp4 = setTempValues[3] * 10;
if (fountainMotor != null)
{
if (fountainMotor.BitNumbers.Count > 0)
{
foreach (var bit in fountainMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isFountainMotorOn = true;
}
}
if (mixerMotor != null)
{
if (mixerMotor.BitNumbers.Count > 0)
{
foreach (var bit in mixerMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isMixerMotorOn = true;
}
}
await WriteToSerialAsync("HeatingPhase");
Dispatcher.UIThread.Post(async () =>
{
footerMsg.Text = "Heating phase";
});
sendComHeating = -1;
}
}
});
}
}
else if (cooling == 1)
{
if (errors.Count > 0)
{
if (!isPaused)
{
//pause = true;
}
}
else
{
if (sendComCooling == 1)
{
foreach (var item in tankBtm.BitNumbers)
{
setTempValues[item - 8] = -1000;
}
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = -1000;
}
foreach (var item in pumb.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.PumbMinHeat;
}
foreach (var item in fount.BitNumbers)
{
setTempValues[item - 8] = (int)recipeCoolingGoal;
}
holdingRegister.setTemp1 = setTempValues[0] * 10;
holdingRegister.setTemp2 = setTempValues[1] * 10;
holdingRegister.setTemp3 = setTempValues[2] * 10;
holdingRegister.setTemp4 = setTempValues[3] * 10;
if (fountainMotor != null)
{
if (fountainMotor.BitNumbers.Count > 0)
{
foreach (var bit in fountainMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isFountainMotorOn = true;
}
}
if (mixerMotor != null)
{
if (mixerMotor.BitNumbers.Count > 0)
{
foreach (var bit in mixerMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isMixerMotorOn = true;
}
}
await WriteToSerialAsync("CoolingPhase");
Dispatcher.UIThread.Post(async () =>
{
footerMsg.Text = "Cooling phase";
});
sendComCooling = -1;
}
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Settings result)
{
if (comFountainTemp * 10 <= (result._recipeTable?.CoolingGoal * 10) + screenData.warningLimit &&
comFountainTemp * 10 > (result._recipeTable?.CoolingGoal * 10) - screenData.warningLimit)
{
if (setCoolingTimerOnce == 1)
{
coolingTimer = new Timer(CoolingTimer, null, 0, 1000);
coolingSeconds = _machine.CoolingDelay;
setCoolingTimerOnce = -1;
}
}
}
});
}
}
else if (pouring == 1)
{
if (errors.Count > 0)
{
if (!isPaused)
{
//pause = true;
}
}
else
{
if (sendComPouring == 1)
{
foreach (var item in tankBtm.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat;
}
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.TankMaxHeat;
}
foreach (var item in pumb.BitNumbers)
{
setTempValues[item - 8] = (int)_machine.PumbMaxHeat;
}
foreach (var item in fount.BitNumbers)
{
setTempValues[item - 8] = (int)recipePouringGoal;
}
holdingRegister.setTemp1 = setTempValues[0] * 10;
holdingRegister.setTemp2 = setTempValues[1] * 10;
holdingRegister.setTemp3 = setTempValues[2] * 10;
holdingRegister.setTemp4 = setTempValues[3] * 10;
if (fountainMotor != null)
{
if (fountainMotor.BitNumbers.Count > 0)
{
foreach (var bit in fountainMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isFountainMotorOn = true;
}
}
if (mixerMotor != null)
{
if (mixerMotor.BitNumbers.Count > 0)
{
foreach (var bit in mixerMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isMixerMotorOn = true;
}
}
await WriteToSerialAsync("PouringPhase");
Dispatcher.UIThread.Post(async () =>
{
footerMsg.Text = "Prepare for pouring";
});
sendComPouring = -1;
}
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Settings result)
{
if (comFountainTemp * 10 < (result._recipeTable?.PouringGoal * 10) + screenData.warningLimit &&
comFountainTemp * 10 > (result._recipeTable?.PouringGoal * 10) - screenData.warningLimit)
{
if (setPouringTimerOnce == 1)
{
foreach (var item in tankBtm.BitNumbers)
{
setTempValues[item - 8] = (int)(recipePouringGoal + _machine.PreHeatingTemp);
}
foreach (var item in tankWall.BitNumbers)
{
setTempValues[item - 8] = (int)(recipePouringGoal + _machine.PreHeatingTemp);
}
foreach (var item in pumb.BitNumbers)
{
setTempValues[item - 8] = -1000;
}
foreach (var item in fount.BitNumbers)
{
setTempValues[item - 8] = (int)recipePouringGoal;
}
holdingRegister.setTemp1 = setTempValues[0] * 10;
holdingRegister.setTemp2 = setTempValues[1] * 10;
holdingRegister.setTemp3 = setTempValues[2] * 10;
holdingRegister.setTemp4 = setTempValues[3] * 10;
if (fountainMotor != null)
{
if (fountainMotor.BitNumbers.Count > 0)
{
foreach (var bit in fountainMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isFountainMotorOn = true;
}
}
if (mixerMotor != null)
{
if (mixerMotor.BitNumbers.Count > 0)
{
foreach (var bit in mixerMotor.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
}
isMixerMotorOn = true;
}
}
await WriteToSerialAsync("PouringPhase");
pouringTimer = new Timer(PouringTimer, null, 0, 1000);
pouringSeconds = _machine.PouringDelay;
setPouringTimerOnce = -1;
}
}
}
});
}
}
}
else
{
Dispatcher.UIThread.Post(() =>
{
footerMsg.Text = "Contact Admin";
});
}
}
}
if (PumbOn == 1)
{
//Dispatcher.UIThread.Post(() =>
//{
// recipeStartBtn.IsEnabled = true;
//});
if (pedalMotor == 0) // Manual Pedal
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
settings.pedalDelayTxt.IsVisible = false;
settings.pedalDelayCounter.IsVisible = false;
if (pedalOnTimer != null)
{
pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOnTimer = null;
}
if (pedalOffTimer != null)
{
pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOffTimer = null;
}
}
});
var pedal = _mapping.Find(x => x.Name.ToLower() == "pedal");
if (pedal != null)
{
// READING THE INPUT REGISTER
if (errors.Count == 0)
{
ushort registerValue = (ushort)inputValues[1];
if (allPedalBitsOn != pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0))
{
allPedalBitsOn = pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0);
pedalStateChanged = 1;
}
else
{
pedalStateChanged = 0;
}
if (!allPedalBitsOn)
{
pedalState = 1;// All bits ON
}
else
{
pedalState = 0; // At least one bit is OFF
}
// READING THE motor REGISTER
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
bool valueChanged = false;
if (pedalState == 1) // If all monitored bits are ON
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
result.pedalUnderLine.Fill = Brush.Parse(result.PassiveColor);
}
});
if (!(comPumpTemp <= recipeCoolingGoal - 3))
{
foreach (var bit in fount.BitNumbers)
{
if (!ToBinary(holdingRegister.motor)[bit])
{
//Debug.WriteLine("input value:" + registerValue);
//Debug.WriteLine("pedal on:" + allBitsOn);
holdingRegister.motor |= (ushort)(1 << bit);
valueChanged = true;
}
}
if (valueChanged)
{
await WriteToSerialAsync("PedalManual");
valueChanged = false;
if (isPaused)
{
unPause = true;
}
}
}
}
else // If at least one monitored bit is OFF
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
result.pedalUnderLine.Fill = Brush.Parse(result.ActiveColor);
}
});
if (pedalStateChanged == 1)
{
foreach (var bit in fount.BitNumbers)
{
if (ToBinary(holdingRegister.motor)[bit])
{
holdingRegister.motor &= (ushort)~(1 << bit);
valueChanged = true;
}
}
if (valueChanged)
{
await WriteToSerialAsync("PedalManual");
valueChanged = false;
}
}
if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null
))
{
fountainPauseSeconds = 10;
fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000);
}
}
if (pedalStateChanged == 1)
{
// WRITE UPDATED VALUE TO HVO REGISTER
//isWriting = true;
}
}
}
}
}
}
else if (pedalMotor == 1) // auto Pedal
{
const double deadZone = 1.5;
if (pedalState == 0) // on
{
var fountt = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fountt != null)
{
if (fountt.BitNumbers.Count > 0)
{
if (!(comPumpTemp <= recipeCoolingGoal - 3 + deadZone))
{
foreach (var bit in fountt.BitNumbers)
{
holdingRegister.motor |= (ushort)(1 << bit);
isFountainMotorOn = true;
}
await WriteToSerialAsync("PedalAuto");
}
}
else
{
// Turn OFF only if it dropped below the lower threshold
if (comPumpTemp <= recipeCoolingGoal - 3 - deadZone)
{
foreach (var bit in fountt.BitNumbers)
holdingRegister.motor &= (ushort)~(1 << bit);
isFountainMotorOn = false;
await WriteToSerialAsync("PedalAuto - OFF");
}
}
}
else if (pedalState == 1) // off
{
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
foreach (var bit in fount.BitNumbers)
{
holdingRegister.motor &= (ushort)~(1 << bit);
}
await WriteToSerialAsync("PedalAuto");
if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null
))
{
fountainPauseSeconds = 10;
fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000);
}
}
}
}
pedalState = -1;
if (!(comPumpTemp <= recipeCoolingGoal - 3))
{
if (setPedalTimerOnce == 1)
{
pedalOffTimer = new Timer(PedalOffTimer, null, 0, 1000);
setPedalTimerOnce = -1;
}
else if (setPedalTimerOnce == 0)
{
pedalOnTimer = new Timer(PedalOnTimer, null, 0, 1000);
setPedalTimerOnce = -1;
}
}
}
}
//change diag UI
var hvo = ToBinary(holdingRegister.hvOut);
var lvo = ToBinary(holdingRegister.lvOut);
var motor = ToBinary(holdingRegister.motor);
Dispatcher.UIThread.Post(async () =>
{
if (ContentArea.Content is Diagnostics diagnostics)
{
foreach (var item in diagnostics.MotoreState.OfType<Grid>().ToList())
{
var stackPanel = item.Children[0] as StackPanel;
var text = stackPanel.Children[1] as TextBlock;
var border = item.Children[1] as Border;
if (motor[int.Parse(item.Tag.ToString())])
{
text.Text = "ON";
border.Background = Brush.Parse(diagnostics.PinkColor);
diagnostics.MotoreState.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.OrangeColor);
}
else
{
text.Text = "OFF";
border.Background = Brush.Parse(diagnostics.GrayColor);
diagnostics.MotoreState.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor);
}
}
// HVO
foreach (var item in diagnostics.hvoOutPuts.OfType<Grid>().ToList())
{
var text = item.Children[1] as TextBlock;
var border = item.Children[2] as Border;
if (hvo[int.Parse(item.Tag.ToString())])
{
text.Text = "ON";
border.Background = Brush.Parse(diagnostics.PinkColor);
diagnostics.hvoOutPuts.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.OrangeColor);
}
else
{
text.Text = "OFF";
border.Background = Brush.Parse(diagnostics.GrayColor);
diagnostics.hvoOutPuts.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor);
}
}
// LVO
foreach (var item in diagnostics.lvoOutPuts.OfType<Grid>().ToList())
{
var text = item.Children[1] as TextBlock;
var border = item.Children[2] as Border;
if (lvo[int.Parse(item.Tag.ToString())])
{
text.Text = "ON";
border.Background = Brush.Parse(diagnostics.PinkColor);
diagnostics.lvoOutPuts.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor);
}
else
{
text.Text = "OFF";
border.Background = Brush.Parse(diagnostics.GrayColor);
diagnostics.lvoOutPuts.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor);
}
}
foreach (var item in diagnostics.lvoOutPuts.OfType<StackPanel>().ToList())
{
var text = item.Children[1] as TextBlock;
var border = item.Children[2] as Border;
if (lvo[int.Parse(item.Tag.ToString())])
{
text.Text = "ON";
border.Background = Brush.Parse(diagnostics.PinkColor);
diagnostics.lvoOutPuts.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor);
}
else
{
text.Text = "OFF";
border.Background = Brush.Parse(diagnostics.GrayColor);
diagnostics.lvoOutPuts.OfType<Ellipse>().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor);
}
}
}
});
await Task.Delay(100);
}
}
catch (Exception e)
{
}
}
}
}
catch
{
}
finally
{
}
}
// Find the port name corresponding to this serial number
Thread.Sleep(50); // Check every 1 seconds
}
}
public bool ConnectToSerialPort()
{
screenData = _screeen.ReadScreens()?[0];
try
{
if (_port != null && _port.IsOpen)
{
_port.Close();
}
_port = null;
_port = new SerialPort(screenData.port, screenData.boundRate);
switch (screenData.parity)
{
case 0:
_port.Parity = Parity.None;
break;
case 1:
_port.Parity = Parity.Odd;
break;
case 2:
_port.Parity = Parity.Even;
break;
case 3:
_port.Parity = Parity.Mark;
break;
case 4:
_port.Parity = Parity.Space;
break;
default:
_port.Parity = Parity.None;
break;
}
switch (screenData.stopBits)
{
case 2:
_port.StopBits = StopBits.Two;
break;
default:
_port.StopBits = StopBits.One;
break;
}
_port.DataBits = 8;
_port.Handshake = Handshake.None;
_port.DtrEnable = true;
// Open the serial port
_port.Open();
return true;
}
catch (Exception ex)
{
Console.WriteLine($"Error connecting to port {screenData.port}: {ex.Message}");
_port = null;
return false;
}
}
public void closeConnection()
{
isRunning = false;
monitorThread.Abort();
}
private async void OnClosing1(object? sender, CancelEventArgs e)
{
closeConnection();
}
private void OnClosingWindow(object? sender, WindowClosingEventArgs e)
{
if (_port != null && _port.IsOpen)
{
_port.Close();
//_port = null;
}
// Example: Cancel the close if needed
// e.Cancel = true;
}
//Main Window Functions
private void errorLogoClick(object? sender, RoutedEventArgs e)
{
errorPopupOverlay.IsVisible = true;
//errorTitel.Text = errorLogo.Tag.ToString();
errorMsg.Text = errorMsg.Text.Trim();
}
private void warningLogoClick(object? sender, RoutedEventArgs e)
{
warningPopupOverlay.IsVisible = true;
warningTitel.Text = warningLogo.Tag.ToString();
warningMsg.Text = warningMsg.Text.Trim();
}
private void HomeTraclBtn(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is Settings result)
{
result.DeletePopupOverlay.IsVisible = true;
result.DeletePopupOverlay.Tag = "home";
}
else if (ContentArea.Content is Diagnostics diagnostics)
{
restBoard = true;
this.UserName.Content = "Select User";
footerMsg.Text = "";
ContentArea.Content = new Home(this);
}
else
{
this.UserName.Content = "Select User";
footerMsg.Text = "";
ContentArea.Content = new Home(this);
}
}
private void DiagnosticsBtn(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is AdvanceSettings advanceSettings)
{
footerMsg.Text = "";
ContentArea.Content = new Diagnostics(this, true);
}
else if (ContentArea.Content is ManualControl)
{
footerMsg.Text = "";
ContentArea.Content = new Diagnostics(this, false, true);
}
else
{
footerMsg.Text = "";
ContentArea.Content = new Diagnostics(this);
}
}
private void ChefManualBtn(object? sender, RoutedEventArgs e)
{
footerMsg.Text = "";
ContentArea.Content = new ManualControl(this);
}
public void AdvanceSettingsView(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is Diagnostics)
{
ContentArea.Content = new AdvanceSettings(this, true, false);
}
else if (ContentArea.Content is Software)
{
ContentArea.Content = new AdvanceSettings(this, false, true);
}
else
{
ContentArea.Content = new AdvanceSettings(this);
}
}
private void RecipeSelTrackBtn(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is Settings result)
{
result.DeletePopupOverlay.IsVisible = true;
result.DeletePopupOverlay.Tag = "recipeSel";
}
else
{
footerMsg.Text = "";
ContentArea.Content = new Recipe(this, Program.currentUser);
}
}
private void SettingTrackBtn(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is Diagnostics diagnostics)
{
restBoard = true;
}
footerMsg.Text = "";
ContentArea.Content = new Admin(this, Program.currentUser);
}
private void SoftwareBtn(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is AdvanceSettings)
{
footerMsg.Text = "";
ContentArea.Content = new Software(this, true);
}
else if (ContentArea.Content is ManualControl)
{
footerMsg.Text = "";
ContentArea.Content = new Software(this, false, true);
}
else
{
footerMsg.Text = "";
ContentArea.Content = new Software(this);
}
}
private async void PreHeatingClick(object? sender, RoutedEventArgs e)
{
if (ContentArea.Content is Settings result)
{
if (result.recipeSettings.IsEnabled)
{
startPreHeating = 1;
writingMaxTemp = 1;
//if (!isMixerMotorOn)
//{
// result.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
//}
//if (!isFountainMotorOn)
//{
// result.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
//}
}
else
{
startPreHeating = 0;
writingMaxTemp = 0;
isFlashPreHeating = false;
}
}
}
//Mixer
public async void MotorClick(object? sender, RoutedEventArgs e)
{
if (!isMixerMotorOn)
{
isMixerMotorOn = true;
checkMixerTWT_HWTH = true;
setMixerTimerOnce = true;
}
else
{
isMixerMotorOn = false;
checkMixerTWT_HWTH = false;
startMixerMotorFlashing = 0;
sendComMixerMotor = 0;
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
settings.mixerDelayTxt.IsVisible = false;
settings.mixerDelayCounter.IsVisible = false;
}
});
if (mixerTimer != null)
{
mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
mixerTimer = null;
}
}
}
private void MixerTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
if (comTankTemp >= recipeCoolingGoal - 3)
{
mixerSeconds--;
}
else
{
//mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
if (mixerSeconds <= 0)
{
// Stop the timer after 15 seconds
settings.mixerDelayTxt.IsVisible = false;
settings.mixerDelayCounter.IsVisible = false;
if (mixerTimer != null)
{
mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
mixerTimer = null;
}
startMixerMotorFlashing = 0;
sendComMixerMotor = 1;
return;
}
if (mixerSeconds <= _machine.MixerDelay)
{
settings.mixerDelayTxt.IsVisible = true;
settings.mixerDelayCounter.Text = mixerSeconds.ToString();
settings.mixerDelayCounter.IsVisible = true;
}
}
});
}
private void StopMixerTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
if (comTankTemp <= recipeCoolingGoal - 3)
{
stopMixerSecondes--;
}
else
{
//mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
if (stopMixerSecondes <= 0)
{
sendComMixerMotor = 0;
stopMixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
stopMixerTimer = null;
return;
}
}
});
}
//Fountain
public async void FountainClick(object? sender, RoutedEventArgs e)
{
if (!isFountainMotorOn)
{
isFountainMotorOn = true;
checkFountainTMT_PMT = true;
setFountainTimerOnce = true;
}
else
{
isFountainMotorOn = false;
checkFountainTMT_PMT = false;
startFountainMotorFlashing = 0;
sendComFountainMotor = 0;
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
settings.fountainDelayTxt.IsVisible = false;
settings.fountainDelayCounter.IsVisible = false;
settings.fountainTargetTxt.IsVisible = false;
settings.fountainTagetTemp.IsVisible = false;
}
});
if (fountainTimer != null)
{
fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainTimer = null;
}
}
}
private void FountainTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
if (comPumpTemp >= recipeCoolingGoal - 3)
{
fountainSeconds--;
}
else
{
//fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
if (fountainSeconds <= 0)
{
// Stop the timer after 15 seconds
settings.fountainDelayTxt.IsVisible = false;
settings.fountainDelayCounter.IsVisible = false;
settings.fountainTargetTxt.IsVisible = false;
settings.fountainTagetTemp.IsVisible = false;
if (fountainTimer != null)
{
fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainTimer = null;
}
startFountainMotorFlashing = 0;
sendComFountainMotor = 1;
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
if (startRecipe == 1 && !isPaused)
{
PumbOn = 1;
}
if (result._recipeTable.Pedal.Value)
{
pedalMotor = 0;
}
else
{
pedalMotor = 1;
pedalState = 0;
setPedalTimerOnce = 1;
}
}
});
return;
}
if (fountainSeconds <= _machine.PumbDelay)
{
settings.fountainDelayTxt.Text = "Chocolate Delay: ";
settings.fountainDelayTxt.IsVisible = true;
settings.fountainDelayCounter.Text = fountainSeconds.ToString();
settings.fountainDelayCounter.IsVisible = true;
settings.fountainTagetTemp.IsVisible = false;
settings.fountainTargetTxt.IsVisible = false;
}
}
});
}
private void StopFountainTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
if (comPumpTemp <= recipeCoolingGoal - 3)
{
stopFountainSecondes--;
}
else
{
//mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
if (stopFountainSecondes <= 0)
{
sendComFountainMotor = 0;
stopFountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
stopFountainTimer = null;
return;
}
}
});
}
private void FountainPauseTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (allBitsOn != fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0))
{
allBitsOn = fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0);
}
if (fountainPauseSeconds <= 0)
{
pause = true;
if (fountainPauseTimer != null)
{
fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainPauseTimer = null;
}
return;
}
if (!allBitsOn)
{
//motor is off
//increase the counter
fountainPauseSeconds--;
//footerMsg.Text ="Fountain is off recipe will pause after: "+ fountainPauseSeconds.ToString();
}
else
{
//motor is on
//cancel the timer
if (fountainPauseTimer != null)
{
fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainPauseTimer = null;
}
}
//if the counter greater than 10 then pause the recipe
});
}
private void NoChoiceChoosenTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
//increase the coiunter
if (ContentArea.Content is Settings settings)
{
if (settings.tempErrorPopupOverlay.IsVisible)
{
noChoiceChoosenSeconds++;
//footerMsg.Text = "sec" + noChoiceChoosenSeconds.ToString();
}
else
{
//stop the timer
if (noChoiceChoosenTimer != null)
{
noChoiceChoosenTimer.Change(Timeout.Infinite, Timeout.Infinite);
noChoiceChoosenTimer = null;
}
}
if (noChoiceChoosenSeconds >= 180)//change to 3 min
{
//if it reach the 3 min then stop the recipe
startRecipe = 0;
Heating = 0;
cooling = 0;
pouring = 0;
PumbOn = -1;
pedalMotor = -1;
if (heatingTimer != null)
{
heatingTimer.Change(Timeout.Infinite, Timeout.Infinite);
heatingSeconds = _machine.HeatingDelay;
heatingTimer = null;
}
if (coolingTimer != null)
{
coolingTimer.Change(Timeout.Infinite, Timeout.Infinite);
coolingSeconds = _machine.CoolingDelay;
coolingTimer = null;
}
if (pouringTimer != null)
{
pouringTimer.Change(Timeout.Infinite, Timeout.Infinite);
pouringSeconds = _machine.PouringDelay;
pouringTimer = null;
}
if (pedalOffTimer != null)
{
pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOffSeconds = 0;
}
if (pedalOnTimer != null)
{
pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOnSeconds = 0;
}
if (fountainPauseTimer != null)
{
fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainPauseSeconds = 10;
fountainPauseTimer = null;
}
if (fountainTimer != null)
{
fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainTimer = null;
}
if (mixerTimer != null)
{
mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
mixerTimer = null;
}
var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
if (fount != null)
{
if (fount.BitNumbers.Count > 0)
{
foreach (var bit in fount.BitNumbers)
{
holdingRegister.motor &= (ushort)~(1 << bit);
}
}
}
startPreHeating = 0;
writingMaxTemp = 0;
isFlashPreHeating = false;
holdingRegister.setTemp1 = -10000;
holdingRegister.setTemp2 = -10000;
holdingRegister.setTemp3 = -10000;
holdingRegister.setTemp4 = -10000;
settings.tempErrorPopupOverlay.IsVisible = false;
Dispatcher.UIThread.Post(async () =>
{
await WriteToSerialAsync("NoChoiceChoosenTimer");
recipeStartBtn.Foreground = Avalonia.Media.Brushes.White;
recipeStartBtn.Background = Brush.Parse("#008000");
footerMsg.Text = "waitting for too long... Recipe Stoped";
recipeStartBtn.Content = "START RECIPE";
PreHeatingBtn.IsEnabled = true;
recipeStartBtn.IsEnabled = true;
});
}
}
});
}
private void HeatingTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
if (fountainPauseTimer == null)
{
if ((comFountainTemp * 10 <= (recipeHeatingGoal * 10) - (screenData.errorLimit * 10) || comFountainTemp * 10 >= (recipeHeatingGoal * 10) + (screenData.errorLimit * 10)) && !pauseTempTracking)
{
// show error window
if (noChoiceChoosenTimer == null)
{
noChoiceChoosenSeconds = 0;
noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000);
}
settings.tempErrorPopupOverlay.IsVisible = true;
}
else if (!pauseTimer)
{
// emty error and warning temp is fine
//warningMessage = "";
//continue counting
heatingSeconds--;
Heating = 1;
}
//warning
if (comFountainTemp * 10 <= (recipeHeatingGoal * 10) - (screenData.warningLimit * 10) || comFountainTemp * 10 >= (recipeHeatingGoal * 10) + (screenData.warningLimit * 10))
{
// show waring and delet error if located
if (warningMessage != "Can Not Locate Temperature Correctly")
{
warningMessage = "Can Not Locate Temperature Correctly";
}
}
else
{
warningMessage = "";
}
if (heatingSeconds <= 0)
{
// Stop the timer after 15 seconds
warningMessage = "";
heatingTimer.Change(Timeout.Infinite, Timeout.Infinite);
pauseTimer = false;
pauseTempTracking = false;
startRecipe = 1;
Heating = -1;
cooling = 1;
sendComCooling = 1;
setCoolingTimerOnce = 1;
heatingTimer = null;
}
if (heatingSeconds <= _machine.HeatingDelay && !pauseTimer)
{
footerMsg.Text = "Heating delay: " + heatingSeconds.ToString();
}
}
}
});
}
private void CoolingTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings settings)
{
if (fountainPauseTimer == null)
{
if ((comFountainTemp * 10 <= (recipeCoolingGoal * 10) - (screenData.errorLimit * 10) || comFountainTemp * 10 >= (recipeCoolingGoal * 10) + (screenData.errorLimit * 10)) && !pauseTempTracking)
{
// show error window
if (noChoiceChoosenTimer == null)
{
noChoiceChoosenSeconds = 0;
noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000);
}
settings.tempErrorPopupOverlay.IsVisible = true;
}
else if (!pauseTimer)
{
// emty error and warning temp is fine
//warningMessage = "";
//continue counting
coolingSeconds--;
}
//warning
if (comFountainTemp * 10 <= (recipeCoolingGoal * 10) - (screenData.warningLimit * 10) || comFountainTemp * 10 >= (recipeCoolingGoal * 10) + (screenData.warningLimit * 10))
{
// show waring and delet error if located
if (warningMessage != "Can Not Locate Temperature Correctly")
{
warningMessage = "Can Not Locate Temperature Correctly";
}
}
else
{
warningMessage = "";
}
if (coolingSeconds <= 0)
{
// Stop the timer after 15 seconds
warningMessage = "";
coolingTimer.Change(Timeout.Infinite, Timeout.Infinite);
pauseTimer = false;
pauseTempTracking = false;
pouring = 1;
sendComPouring = 1;
setPouringTimerOnce = 1;
cooling = -1;
coolingTimer = null;
}
if (coolingSeconds <= _machine.CoolingDelay && !pauseTimer)
{
footerMsg.Text = "Cooling delay: " + coolingSeconds.ToString();
}
}
}
});
}
private void PouringTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
try
{
if (ContentArea.Content is Settings settings)
{
if (fountainPauseTimer == null)
{
if ((comFountainTemp * 10 <= (recipePouringGoal * 10) - (screenData.errorLimit * 10) || comFountainTemp * 10 >= (recipePouringGoal * 10) + (screenData.errorLimit * 10)) && !pauseTempTracking)
{
// show error window
if (noChoiceChoosenTimer == null)
{
noChoiceChoosenSeconds = 0;
noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000);
}
settings.tempErrorPopupOverlay.IsVisible = true;
}
else if (!pauseTimer)
{
// emty error and warning temp is fine
//warningMessage = "";
//continue counting
pouringSeconds--;
}
//warning
if (comFountainTemp * 10 <= (recipePouringGoal * 10) - (screenData.warningLimit * 10) || comFountainTemp * 10 >= (recipePouringGoal * 10) + (screenData.warningLimit * 10))
{
// show waring and delet error if located
if (warningMessage != "Can Not Locate Temperature Correctly")
{
warningMessage = "Can Not Locate Temperature Correctly";
}
}
else
{
warningMessage = "";
}
if (pouringSeconds <= 0)
{
// Stop the timer after 15 seconds
if (pouringTimer != null)
{
pouringTimer.Change(Timeout.Infinite, Timeout.Infinite);
pouringTimer = null;
}
pauseTimer = false;
pauseTempTracking = false;
//pouring = -1;
//PumbOn = 1;
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
//if (result._recipeTable.Pedal.Value)
//{
// pedalMotor = 0;
//}
//else
//{
// pedalMotor = 1;
// pedalState = 0;
// setPedalTimerOnce = 1;
//}
footerMsg.Text = "Ready for pouring";
}
});
}
if (pouringSeconds <= _machine.PouringDelay && !pauseTimer)
{
footerMsg.Text = "Pouring delay: " + pouringSeconds.ToString();
}
}
}
}
catch (Exception ex)
{
footerMsg.Text = $"Error: {ex.Message}";
}
});
}
private void PedalOffTimer(object state)
{
Dispatcher.UIThread.Post(() =>
{
// Stop the timer after 15 seconds
if (ContentArea.Content is Settings result)
{
pedalOffSeconds++;
if (pedalOffSeconds <= result._recipeTable.PedalOffTime)
{
result.pedalDelayTxt.Text = "Pedal ON: ";
result.pedalDelayCounter.Text = pedalOffSeconds.ToString();
result.pedalDelayTxt.IsVisible = true;
result.pedalDelayCounter.IsVisible = true;
}
if (pedalOffSeconds >= result._recipeTable.PedalOffTime)
{
pedalOffSeconds = 0;
PumbOn = 1;
pedalMotor = 1;
pedalState = 1;
setPedalTimerOnce = 0;
if (pedalOffTimer != null)
{
pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOffTimer = null;
}
}
}
});
}
private void PedalOnTimer(object state)
{
Dispatcher.UIThread.Invoke(() =>
{
if (ContentArea.Content is Settings result)
{
pedalOnSeconds++;
if (pedalOnSeconds <= result._recipeTable.PedalOnTime)
{
result.pedalDelayTxt.Text = "Pedal OFF: ";
result.pedalDelayCounter.Text = pedalOnSeconds.ToString();
result.pedalDelayTxt.IsVisible = true;
result.pedalDelayCounter.IsVisible = true;
}
if (pedalOnSeconds >= result._recipeTable.PedalOnTime)
{
pedalOnSeconds = 0;
PumbOn = 1;
pedalMotor = 1;
pedalState = 0;
setPedalTimerOnce = 1;
if (pedalOnTimer != null)
{
pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOnTimer = null;
}
}
}
});
}
//Recipe Start
public async void RecipeStartBtn(object? sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (startRecipe == 0)
{
startRecipe = 1;
stopRecipeFlag = false;
if (ContentArea.Content is Settings result)
{
recipeHeatingGoal = result._recipeTable.HeatingGoal;
recipeCoolingGoal = result._recipeTable.CoolingGoal;
recipePouringGoal = result._recipeTable.PouringGoal;
if (comPumpTemp * 10 < _machine.PumbMaxHeat * 10 || comTankTemp * 10 < _machine.TankMaxHeat * 10)
{
startPreHeating = 1;
writingMaxTemp = 1;
// Assuming you have a Button named myButton
}
if (!isMixerMotorOn)
{
result.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
if (!isFountainMotorOn)
{
result.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
Dispatcher.UIThread.Post(() =>
{
result.mixerBtn.IsEnabled = false;
result.fountainBtn.IsEnabled = false;
PreHeatingBtn.IsEnabled = false;
recipeStartBtn.IsEnabled = true;
button.Background = Avalonia.Media.Brushes.Red;
button.Content = "STOP RECIPE";
});
}
}
else if (startRecipe == 1)
{
startRecipe = 0;
stopRecipeFlag = true;
Heating = -1;
cooling = -1;
pouring = -1;
PumbOn = -1;
pedalMotor = -1;
if (heatingTimer != null)
{
heatingTimer.Change(Timeout.Infinite, Timeout.Infinite);
heatingSeconds = _machine.HeatingDelay;
heatingTimer = null;
}
if (coolingTimer != null)
{
coolingTimer.Change(Timeout.Infinite, Timeout.Infinite);
coolingSeconds = _machine.CoolingDelay;
coolingTimer = null;
}
if (pouringTimer != null)
{
pouringTimer.Change(Timeout.Infinite, Timeout.Infinite);
pouringSeconds = _machine.PouringDelay;
pouringTimer = null;
}
if (pedalOffTimer != null)
{
pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOffSeconds = 0;
}
if (pedalOnTimer != null)
{
pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOnSeconds = 0;
}
if (fountainPauseTimer != null)
{
fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainPauseSeconds = 10;
fountainPauseTimer = null;
}
if (fountainTimer != null)
{
fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainTimer = null;
}
if (mixerTimer != null)
{
mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
mixerTimer = null;
}
if (ContentArea.Content is Settings settings)
{
if (isMixerMotorOn)
{
settings.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
if (isFountainMotorOn)
{
settings.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
}
settings.mixerDelayTxt.IsVisible = false;
settings.mixerDelayCounter.IsVisible = false;
settings.fountainDelayTxt.IsVisible = false;
settings.fountainDelayCounter.IsVisible = false;
settings.fountainTargetTxt.IsVisible = false;
settings.fountainTagetTemp.IsVisible = false;
}
//var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower());
//if (fount != null)
//{
// if (fount.BitNumbers.Count > 0)
// {
// foreach (var bit in fount.BitNumbers)
// {
// holdingRegister.motor &= (ushort)~(1 << bit);
// }
// }
//}
startPreHeating = 0;
writingMaxTemp = 0;
isFlashPreHeating = false;
holdingRegister.setTemp1 = -10000;
holdingRegister.setTemp2 = -10000;
holdingRegister.setTemp3 = -10000;
holdingRegister.setTemp4 = -10000;
holdingRegister.motor = 0;
await WriteToSerialAsync("RecipeStop");
footerMsg.Text = "Recipe Stoped";
button.Content = "START RECIPE";
PreHeatingBtn.IsEnabled = true;
recipeStartBtn.IsEnabled = true;
Dispatcher.UIThread.Post(() =>
{
if (ContentArea.Content is Settings result)
{
result.mixerBtn.IsEnabled = true;
result.fountainBtn.IsEnabled = true;
result.pedalDelayTxt.IsVisible = false;
result.pedalDelayCounter.IsVisible = false;
}
recipeStartBtn.Foreground = Avalonia.Media.Brushes.White;
recipeStartBtn.Background = Brush.Parse("#008000");
});
}
}
}
public void resetAll()
{
if (heatingTimer != null)
{
heatingTimer.Change(Timeout.Infinite, Timeout.Infinite);
heatingSeconds = _machine.HeatingDelay;
heatingTimer = null;
}
if (coolingTimer != null)
{
coolingTimer.Change(Timeout.Infinite, Timeout.Infinite);
coolingSeconds = _machine.CoolingDelay;
coolingTimer = null;
}
if (pouringTimer != null)
{
pouringTimer.Change(Timeout.Infinite, Timeout.Infinite);
pouringSeconds = _machine.PouringDelay;
pouringTimer = null;
}
if (pedalOffTimer != null)
{
pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOffSeconds = 0;
}
if (pedalOnTimer != null)
{
pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite);
pedalOnSeconds = 0;
}
if (fountainPauseTimer != null)
{
fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainPauseSeconds = 10;
fountainPauseTimer = null;
}
if (fountainTimer != null)
{
fountainTimer.Change(Timeout.Infinite, Timeout.Infinite);
fountainTimer = null;
}
if (mixerTimer != null)
{
mixerTimer.Change(Timeout.Infinite, Timeout.Infinite);
mixerTimer = null;
}
pedalState = -1;
pedalStateChanged = -1;
recipeHeatingGoal = 0;
recipeCoolingGoal = 0;
recipePouringGoal = 0;
//pre Heating
isFlashPreHeating = false;
startPreHeating = -1;
writingMaxTemp = -1;
// mixer
mixerSeconds = 1;
setMixerTimerOnce = false;
checkMixerTWT_HWTH = false;
isMixerMotorOn = false;
startMixerMotor = -1;
startMixerMotorFlashing = -1;
sendComMixerMotor = -1;
//Fountain Motor
fountainSeconds = 1;
setFountainTimerOnce = false;
checkFountainTMT_PMT = false;
isFountainMotorOn = false;
startFountainMotor = -1;
startFountainMotorFlashing = -1;
sendComFountainMotor = -1;
//MOLD HEATER(off:0,on:1) , VIBRATION(off:0,on:1) , VIB. HEATER(off:0,on:1)
moldHeaterMotor = -1;
vibrationMotor = -1;
vibHeaterMotor = -1;
//Pedal(manual=0,auto=1)
pedalMotor = -1;
//Recipe Start
startRecipe = 0;
sendComTankTemp = -1;
//phase 1 heating
Heating = -1;
sendComHeating = -1;
setHeatingTimerOnce = -1;
heatingSeconds = 0;
//phase 2 cooling
cooling = -1;
sendComCooling = -1;
setCoolingTimerOnce = -1;
coolingSeconds = 0;
//phase 3 pouring
pouring = -1;
sendComPouring = -1;
setPouringTimerOnce = -1;
pouringSeconds = 0;
//start the pumb
PumbOn = -1;
pedalOffSeconds = 0;
pedalOnSeconds = 0;
setPedalTimerOnce = -1;
Dispatcher.UIThread.Post(() =>
{
recipeStartBtn.Foreground = Avalonia.Media.Brushes.White;
recipeStartBtn.Background = Brush.Parse("#008000");
recipeStartBtn.Content = "START RECIPE";
PreHeatingBtn.IsEnabled = true;
recipeStartBtn.IsEnabled = true;
});
}
private async void ResetErrors(object? sender, RoutedEventArgs e)
{
holdingRegister.resetError = (ushort)(1 << 0);
await WriteToSerialAsync("ResetErrors");
}
private async void OnWarningPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
warningPopupOverlay.IsVisible = false;
}
private async void OnErrorPopupOverlayPointerPressed(object? sender, RoutedEventArgs e)
{
errorPopupOverlay.IsVisible = false;
}
public static class MessageBox
{
public static async Task Show(Window owner, string message, string title)
{
var dialog = new Window
{
Title = title,
Width = 300,
Height = 150,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Topmost = false,
Content = new StackPanel
{
Children =
{
new TextBlock
{
Text = message,
Margin = new Thickness(10),
HorizontalAlignment = HorizontalAlignment.Center
},
new Button
{
Content = "OK",
Margin = new Thickness(10),
HorizontalAlignment = HorizontalAlignment.Center
}
}
}
};
var button = (Button)((StackPanel)dialog.Content).Children[1];
button.Click += (s, e) => dialog.Close();
owner.Topmost = false;
await dialog.ShowDialog(owner);
owner.Topmost = true;
owner.Activate();
// Restart keyboard to bring it on top
var (fileName, args) = GetKeyboardCommand();
if (!string.IsNullOrEmpty(fileName))
{
try
{
Process.Start(fileName, args);
}
catch
{
// Handle exceptions if needed
}
}
}
private static (string? fileName, string args) GetKeyboardCommand()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
return ("osk.exe", "");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
return ("onboard", ""); // or "florence", "matchbox-keyboard"
return (null, "");
}
}
}
}
============================================================
FILE: DaireApplication/App.axaml
============================================================
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="DaireApplication.App"
xmlns:local="using:DaireApplication"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
============================================================
FILE: DaireApplication/App.axaml.cs
============================================================
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using DaireApplication.ViewModels;
using DaireApplication.Views;
namespace DaireApplication
{
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
// Migrate CSV files by adding missing columns with default values
DataBase.DataPathManager.MigrateCsvFiles();
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
}
}
============================================================
FILE: DaireApplication/app.manifest
============================================================
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="DaireApplication.Desktop"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
============================================================
FILE: DaireApplication/Program.cs
============================================================
using Avalonia;
using Avalonia.Controls;
using Avalonia.ReactiveUI;
using AvaloniaApplication1.DataBase;
using System;
using System.Threading.Tasks;
namespace DaireApplication
{
internal sealed class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);
public static UserTable? currentUser;
public static int pouringMinTemp = -5;
public static int absoluteMaxTemp = 70;
public static int absoluteMinTemp = -10;
// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace()
.UseReactiveUI();
}
}
============================================================
FILE: DaireApplication/ViewLocator.cs
============================================================
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using DaireApplication.ViewModels;
using System;
namespace DaireApplication
{
public class ViewLocator : IDataTemplate
{
public Control? Build(object? param)
{
if (param is null)
return null;
var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal);
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object? data)
{
return data is ViewModelBase;
}
}
}
============================================================
FILE: README.md
============================================================
# copyVersoin
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command:
```
cd existing_repo
git remote add origin https://gitlab.com/wael.badawi2000/copyversoin.git
git branch -M main
git push -uf origin main
```
## Integrate with your tools
- [ ] [Set up project integrations](https://gitlab.com/wael.badawi2000/copyversoin/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.