initial version [by claude]
This commit is contained in:
commit
bd857a4e52
10
.claude/settings.local.json
Normal file
10
.claude/settings.local.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"WebSearch",
|
||||||
|
"WebFetch(domain:github.com)"
|
||||||
|
],
|
||||||
|
"deny": [],
|
||||||
|
"ask": []
|
||||||
|
}
|
||||||
|
}
|
||||||
69
.gitignore
vendored
Normal file
69
.gitignore
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Garmin Connect IQ Build Artifacts
|
||||||
|
*.prg
|
||||||
|
*.iq
|
||||||
|
bin/
|
||||||
|
*.debug.xml
|
||||||
|
|
||||||
|
# Developer Keys (IMPORTANT: Never commit these!)
|
||||||
|
*.der
|
||||||
|
*.pem
|
||||||
|
developer_key
|
||||||
|
developer_key.der
|
||||||
|
|
||||||
|
# IDE Files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
.settings/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
|
||||||
|
# Eclipse/Garmin Plugin
|
||||||
|
.externalToolBuilders/
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
build/
|
||||||
|
target/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
*~
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Generated resources
|
||||||
|
gen/
|
||||||
|
|
||||||
|
# Simulator data
|
||||||
|
.simulator/
|
||||||
|
|
||||||
|
# Barrel files (if not distributing)
|
||||||
|
barrels/
|
||||||
|
|
||||||
|
# Mac OS
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
Desktop.ini
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Linux
|
||||||
|
*~
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Compiled source
|
||||||
|
*.class
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
131
PLAN-metric-watchface.md
Normal file
131
PLAN-metric-watchface.md
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
# Decimal Day Progress Watchface - Implementation Plan
|
||||||
|
|
||||||
|
## Concept Overview
|
||||||
|
|
||||||
|
Create a joke/novelty Garmin watchface that displays time as a decimal day progress meter instead of traditional 12/24 hour format.
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
- **10 equal divisions** on the watchface (instead of 12 hours)
|
||||||
|
- **Single hand** showing day progress as a decimal (0-10)
|
||||||
|
- **Analog display** with tick marks at each decimal position
|
||||||
|
- **Optional digital readout** showing exact decimal time
|
||||||
|
|
||||||
|
### Time Mapping
|
||||||
|
- Midnight (00:00) → 0.0
|
||||||
|
- 6:00 AM → 2.5
|
||||||
|
- Noon (12:00) → 5.0
|
||||||
|
- 6:00 PM → 7.5
|
||||||
|
- Midnight (24:00) → 10.0 (wraps to 0)
|
||||||
|
|
||||||
|
## Technical Implementation
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
```
|
||||||
|
MetricWatchFace/
|
||||||
|
├── manifest.xml # App metadata and device compatibility
|
||||||
|
├── monkey.jungle # Build configuration
|
||||||
|
├── resources/
|
||||||
|
│ ├── drawables/
|
||||||
|
│ │ └── drawables.xml # Layout definitions
|
||||||
|
│ ├── strings/
|
||||||
|
│ │ └── strings.xml # Localization
|
||||||
|
│ └── settings/
|
||||||
|
│ └── settings.xml # User settings (if needed)
|
||||||
|
└── source/
|
||||||
|
├── MetricWatchFaceApp.mc # Application entry point
|
||||||
|
└── MetricWatchFaceView.mc # Main watchface view logic
|
||||||
|
```
|
||||||
|
|
||||||
|
### Core Calculation
|
||||||
|
|
||||||
|
**Decimal Time Formula:**
|
||||||
|
```
|
||||||
|
decimalTime = (currentHour + currentMinute/60.0 + currentSecond/3600.0) / 24.0 * 10.0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Hand Angle Calculation:**
|
||||||
|
```
|
||||||
|
handAngle = (decimalTime / 10.0) * 360.0 - 90.0 // -90 to start at top (12 o'clock position)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Drawing Components
|
||||||
|
|
||||||
|
1. **Watchface Circle**
|
||||||
|
- Use `drawCircle()` or `drawArc()` for outline
|
||||||
|
- Draw 10 tick marks at 36° intervals (360°/10)
|
||||||
|
|
||||||
|
2. **Decimal Markers**
|
||||||
|
- Place numbers 0-9 around the perimeter
|
||||||
|
- Position 0 at top (traditional 12 o'clock position)
|
||||||
|
- Position 5 at bottom (traditional 6 o'clock position)
|
||||||
|
|
||||||
|
3. **Progress Hand**
|
||||||
|
- Use `fillPolygon()` to draw a triangle/arrow hand
|
||||||
|
- Calculate hand coordinates using trigonometry
|
||||||
|
- Rotate based on current decimal time
|
||||||
|
|
||||||
|
4. **Digital Display** (optional)
|
||||||
|
- Show exact decimal time (e.g., "3.47")
|
||||||
|
- Position at center or bottom of face
|
||||||
|
|
||||||
|
### Key Methods
|
||||||
|
|
||||||
|
**MetricWatchFaceView.mc:**
|
||||||
|
- `initialize()` - Set up initial state
|
||||||
|
- `onUpdate(dc)` - Main rendering method (called periodically)
|
||||||
|
- `computeDecimalTime()` - Calculate current decimal time
|
||||||
|
- `drawWatchFace(dc)` - Draw the analog face and markers
|
||||||
|
- `drawHand(dc, decimalTime)` - Draw the progress hand
|
||||||
|
- `drawDigitalTime(dc, decimalTime)` - Optional digital display
|
||||||
|
|
||||||
|
### Device Compatibility
|
||||||
|
|
||||||
|
Target devices:
|
||||||
|
- Fenix series (5, 6, 7)
|
||||||
|
- Forerunner series (245, 645, 945)
|
||||||
|
- Vivoactive series (3, 4)
|
||||||
|
- Other modern Garmin watches with Connect IQ support
|
||||||
|
|
||||||
|
Considerations:
|
||||||
|
- Handle different screen sizes/resolutions
|
||||||
|
- Support both round and semi-round displays
|
||||||
|
- Test with MIP and AMOLED displays
|
||||||
|
|
||||||
|
## Implementation Steps
|
||||||
|
|
||||||
|
1. **Project Setup**
|
||||||
|
- Create manifest.xml with app metadata
|
||||||
|
- Set up basic directory structure
|
||||||
|
- Create application entry point
|
||||||
|
|
||||||
|
2. **Core Logic**
|
||||||
|
- Implement decimal time calculation
|
||||||
|
- Add time update handling
|
||||||
|
- Create view class structure
|
||||||
|
|
||||||
|
3. **Rendering**
|
||||||
|
- Draw watchface circle and divisions
|
||||||
|
- Add decimal markers (0-9)
|
||||||
|
- Implement hand rotation logic
|
||||||
|
- Add digital display
|
||||||
|
|
||||||
|
4. **Testing & Refinement**
|
||||||
|
- Test in simulator
|
||||||
|
- Verify calculations at key times
|
||||||
|
- Optimize drawing performance
|
||||||
|
- Test on actual device if available
|
||||||
|
|
||||||
|
## Future Enhancements (Optional)
|
||||||
|
|
||||||
|
- Add date display
|
||||||
|
- Include battery indicator
|
||||||
|
- Show step count or other metrics
|
||||||
|
- Customizable colors via settings
|
||||||
|
- Alternative hand styles
|
||||||
|
- Animation effects
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- Garmin Connect IQ SDK Documentation
|
||||||
|
- Swiss Railway Clock example (analog implementation)
|
||||||
|
- Monkey C API reference for graphics primitives
|
||||||
130
README.md
Normal file
130
README.md
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
# Metric Day Progress Watchface
|
||||||
|
|
||||||
|
A novelty Garmin watchface that displays time as decimal day progress instead of traditional 12/24 hour format!
|
||||||
|
|
||||||
|
## Concept
|
||||||
|
|
||||||
|
Instead of the traditional 12-hour clock, this watchface divides the day into **10 equal parts** and displays your progress through the day as a decimal number from 0 to 10.
|
||||||
|
|
||||||
|
### Time Conversions
|
||||||
|
|
||||||
|
- **Midnight (00:00)** → 0.0
|
||||||
|
- **6:00 AM** → 2.5
|
||||||
|
- **Noon (12:00)** → 5.0
|
||||||
|
- **6:00 PM** → 7.5
|
||||||
|
- **End of day (24:00)** → 10.0
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Analog watchface with 10 divisions (0-9)
|
||||||
|
- Rotating red hand showing current day progress
|
||||||
|
- Digital decimal time display
|
||||||
|
- Clean, minimalist design
|
||||||
|
- Supports most modern Garmin devices
|
||||||
|
|
||||||
|
## Building the Watchface
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
1. **Garmin Connect IQ SDK** - Download from [developer.garmin.com](https://developer.garmin.com/connect-iq/sdk/)
|
||||||
|
2. **Java Development Kit (JDK)** - OpenJDK recommended
|
||||||
|
3. **Visual Studio Code** (optional but recommended)
|
||||||
|
4. **Garmin Monkey C Extension** for VS Code (optional)
|
||||||
|
|
||||||
|
### Build Methods
|
||||||
|
|
||||||
|
#### Method 1: Using Visual Studio Code
|
||||||
|
|
||||||
|
1. Open this folder in VS Code
|
||||||
|
2. Ensure the Monkey C extension is installed
|
||||||
|
3. Press the play button in the toolbar
|
||||||
|
4. Select your target device from the simulator
|
||||||
|
|
||||||
|
#### Method 2: Using Command Line
|
||||||
|
|
||||||
|
If you have the SDK installed and `$SDK_PATH` set:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build for simulator
|
||||||
|
$SDK_PATH/bin/monkeyc \
|
||||||
|
-o MetricWatchFace.prg \
|
||||||
|
-f monkey.jungle \
|
||||||
|
-y $SDK_PATH/bin/developer_key
|
||||||
|
|
||||||
|
# Run in simulator
|
||||||
|
$SDK_PATH/bin/connectiq
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Method 3: Using monkeybrains (if available)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
monkeybrains build
|
||||||
|
monkeybrains run
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deploying to a Real Device
|
||||||
|
|
||||||
|
1. Build the `.prg` file using one of the methods above
|
||||||
|
2. Connect your Garmin device via USB
|
||||||
|
3. Copy the `.prg` file to the `GARMIN/APPS` folder on your device
|
||||||
|
4. Safely disconnect the device
|
||||||
|
5. The watchface should now be available in your watchface selection menu
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
MetricWatchFace/
|
||||||
|
├── manifest.xml # App configuration
|
||||||
|
├── monkey.jungle # Build configuration
|
||||||
|
├── source/
|
||||||
|
│ ├── MetricWatchFaceApp.mc # Application entry point
|
||||||
|
│ └── MetricWatchFaceView.mc # Main watchface logic
|
||||||
|
└── resources/
|
||||||
|
├── drawables/
|
||||||
|
│ ├── drawables.xml # Drawable resources
|
||||||
|
│ └── launcher_icon.png # App icon (placeholder)
|
||||||
|
└── strings/
|
||||||
|
└── strings.xml # String resources
|
||||||
|
```
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
The watchface calculates decimal time using the formula:
|
||||||
|
|
||||||
|
```
|
||||||
|
decimalTime = (hours + minutes/60 + seconds/3600) / 24 * 10
|
||||||
|
```
|
||||||
|
|
||||||
|
This value (0.0 to 10.0) is then displayed:
|
||||||
|
- **Graphically** via a rotating red hand on an analog face
|
||||||
|
- **Digitally** as a decimal number at the bottom of the screen
|
||||||
|
|
||||||
|
## Supported Devices
|
||||||
|
|
||||||
|
This watchface supports a wide range of Garmin devices including:
|
||||||
|
- Fenix series (5, 5 Plus, 6, 7)
|
||||||
|
- Forerunner series (245, 645, 945, 955)
|
||||||
|
- Vivoactive series (3, 4)
|
||||||
|
- Venu series (1, 2, 2 Plus)
|
||||||
|
|
||||||
|
See `manifest.xml` for the complete list.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- The launcher icon is currently a placeholder - you can replace it with your own PNG image
|
||||||
|
- The watchface uses a simple black background with white/red elements
|
||||||
|
- Updates occur every second when active to show smooth hand movement
|
||||||
|
|
||||||
|
## Future Enhancements
|
||||||
|
|
||||||
|
Potential improvements:
|
||||||
|
- Add date display
|
||||||
|
- Battery indicator
|
||||||
|
- Step count or other fitness metrics
|
||||||
|
- Customizable colors via settings
|
||||||
|
- Different hand styles
|
||||||
|
- AMOLED-optimized always-on mode
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This is a fun/joke project - feel free to use and modify as you wish!
|
||||||
65
manifest.xml
Normal file
65
manifest.xml
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- Metric Day Progress Watchface Manifest -->
|
||||||
|
<iq:manifest xmlns:iq="http://www.garmin.com/xml/connectiq" version="3">
|
||||||
|
<iq:application entry="MetricWatchFaceApp" id="350d1be0-5312-40bf-bf4d-fffcbd227484" launcherIcon="@Drawables.LauncherIcon" minApiLevel="3.2.0" name="@Strings.AppName" type="watchface" version="1.0.0">
|
||||||
|
<iq:products>
|
||||||
|
<!-- Fenix Series -->
|
||||||
|
<!-- Forerunner Series -->
|
||||||
|
<!-- Vivoactive Series -->
|
||||||
|
<!-- Other devices -->
|
||||||
|
<iq:product id="epix2"/>
|
||||||
|
<iq:product id="epix2pro42mm"/>
|
||||||
|
<iq:product id="epix2pro47mm"/>
|
||||||
|
<iq:product id="epix2pro47mmsystem7preview"/>
|
||||||
|
<iq:product id="epix2pro51mm"/>
|
||||||
|
<iq:product id="fenix6"/>
|
||||||
|
<iq:product id="fenix6pro"/>
|
||||||
|
<iq:product id="fenix6s"/>
|
||||||
|
<iq:product id="fenix6spro"/>
|
||||||
|
<iq:product id="fenix6xpro"/>
|
||||||
|
<iq:product id="fenix7"/>
|
||||||
|
<iq:product id="fenix7pro"/>
|
||||||
|
<iq:product id="fenix7pronowifi"/>
|
||||||
|
<iq:product id="fenix7s"/>
|
||||||
|
<iq:product id="fenix7spro"/>
|
||||||
|
<iq:product id="fenix7x"/>
|
||||||
|
<iq:product id="fenix7xpro"/>
|
||||||
|
<iq:product id="fenix7xpronowifi"/>
|
||||||
|
<iq:product id="fenix843mm"/>
|
||||||
|
<iq:product id="fenix847mm"/>
|
||||||
|
<iq:product id="fenix8pro47mm"/>
|
||||||
|
<iq:product id="fenix8solar47mm"/>
|
||||||
|
<iq:product id="fenix8solar51mm"/>
|
||||||
|
<iq:product id="fenixe"/>
|
||||||
|
<iq:product id="fr255"/>
|
||||||
|
<iq:product id="fr255m"/>
|
||||||
|
<iq:product id="fr255s"/>
|
||||||
|
<iq:product id="fr255sm"/>
|
||||||
|
<iq:product id="fr265"/>
|
||||||
|
<iq:product id="fr265s"/>
|
||||||
|
<iq:product id="fr57042mm"/>
|
||||||
|
<iq:product id="fr57047mm"/>
|
||||||
|
<iq:product id="fr645m"/>
|
||||||
|
<iq:product id="fr945"/>
|
||||||
|
<iq:product id="fr945lte"/>
|
||||||
|
<iq:product id="fr955"/>
|
||||||
|
<iq:product id="fr965"/>
|
||||||
|
<iq:product id="fr970"/>
|
||||||
|
<iq:product id="venu2plus"/>
|
||||||
|
<iq:product id="venu3"/>
|
||||||
|
<iq:product id="venu3s"/>
|
||||||
|
<iq:product id="venu441mm"/>
|
||||||
|
<iq:product id="venu445mm"/>
|
||||||
|
<iq:product id="vivoactive3m"/>
|
||||||
|
<iq:product id="vivoactive4"/>
|
||||||
|
<iq:product id="vivoactive4s"/>
|
||||||
|
<iq:product id="vivoactive5"/>
|
||||||
|
<iq:product id="vivoactive6"/>
|
||||||
|
</iq:products>
|
||||||
|
<iq:permissions/>
|
||||||
|
<iq:languages>
|
||||||
|
<iq:language>eng</iq:language>
|
||||||
|
</iq:languages>
|
||||||
|
<iq:barrels/>
|
||||||
|
</iq:application>
|
||||||
|
</iq:manifest>
|
||||||
1
monkey.jungle
Normal file
1
monkey.jungle
Normal file
@ -0,0 +1 @@
|
|||||||
|
project.manifest = manifest.xml
|
||||||
3
resources/drawables/drawables.xml
Normal file
3
resources/drawables/drawables.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<drawables>
|
||||||
|
<bitmap id="LauncherIcon" filename="launcher_icon.png" />
|
||||||
|
</drawables>
|
||||||
BIN
resources/drawables/launcher_icon.png
Normal file
BIN
resources/drawables/launcher_icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
3
resources/strings/strings.xml
Normal file
3
resources/strings/strings.xml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<strings>
|
||||||
|
<string id="AppName">Metric Day</string>
|
||||||
|
</strings>
|
||||||
23
source/MetricWatchFaceApp.mc
Normal file
23
source/MetricWatchFaceApp.mc
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using Toybox.Application;
|
||||||
|
using Toybox.WatchUi;
|
||||||
|
|
||||||
|
class MetricWatchFaceApp extends Application.AppBase {
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
AppBase.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// onStart() is called on application start up
|
||||||
|
function onStart(state) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// onStop() is called when your application is exiting
|
||||||
|
function onStop(state) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the initial view of your application here
|
||||||
|
function getInitialView() {
|
||||||
|
return [ new MetricWatchFaceView() ];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
174
source/MetricWatchFaceView.mc
Normal file
174
source/MetricWatchFaceView.mc
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
using Toybox.WatchUi;
|
||||||
|
using Toybox.Graphics;
|
||||||
|
using Toybox.System;
|
||||||
|
using Toybox.Lang;
|
||||||
|
using Toybox.Time;
|
||||||
|
using Toybox.Time.Gregorian;
|
||||||
|
|
||||||
|
class MetricWatchFaceView extends WatchUi.WatchFace {
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
WatchFace.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load your resources here
|
||||||
|
function onLayout(dc) {
|
||||||
|
// We draw everything programmatically, no layout needed
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when this View is brought to the foreground. Restore
|
||||||
|
// the state of this View and prepare it to be shown. This includes
|
||||||
|
// loading resources into memory.
|
||||||
|
function onShow() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the view
|
||||||
|
function onUpdate(dc) {
|
||||||
|
// Get the current time
|
||||||
|
var clockTime = System.getClockTime();
|
||||||
|
var decimalTime = computeDecimalTime(clockTime);
|
||||||
|
|
||||||
|
// Clear the screen
|
||||||
|
dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_BLACK);
|
||||||
|
dc.clear();
|
||||||
|
|
||||||
|
// Draw the watchface
|
||||||
|
drawWatchFace(dc);
|
||||||
|
|
||||||
|
// Draw the hand
|
||||||
|
drawHand(dc, decimalTime);
|
||||||
|
|
||||||
|
// Draw digital time display
|
||||||
|
drawDigitalTime(dc, decimalTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when this View is removed from the screen. Save the
|
||||||
|
// state of this View here. This includes freeing resources from
|
||||||
|
// memory.
|
||||||
|
function onHide() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// The user has just looked at their watch. Timers and animations may be started here.
|
||||||
|
function onExitSleep() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terminate any active timers and prepare for slow updates.
|
||||||
|
function onEnterSleep() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute decimal time from current clock time
|
||||||
|
// Returns a value from 0.0 to 10.0 representing the day's progress
|
||||||
|
function computeDecimalTime(clockTime) {
|
||||||
|
var hour = clockTime.hour;
|
||||||
|
var min = clockTime.min;
|
||||||
|
var sec = clockTime.sec;
|
||||||
|
|
||||||
|
// Convert to decimal: (hours + minutes/60 + seconds/3600) / 24 * 10
|
||||||
|
var decimalTime = (hour + (min / 60.0) + (sec / 3600.0)) / 24.0 * 10.0;
|
||||||
|
|
||||||
|
return decimalTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the watchface circle, tick marks, and numbers
|
||||||
|
function drawWatchFace(dc) {
|
||||||
|
var width = dc.getWidth();
|
||||||
|
var height = dc.getHeight();
|
||||||
|
var centerX = width / 2;
|
||||||
|
var centerY = height / 2;
|
||||||
|
var radius = (width < height ? width : height) / 2 - 10;
|
||||||
|
|
||||||
|
// Draw outer circle
|
||||||
|
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
|
||||||
|
dc.setPenWidth(3);
|
||||||
|
dc.drawCircle(centerX, centerY, radius);
|
||||||
|
|
||||||
|
// Draw tick marks and numbers for each decimal position (0-9)
|
||||||
|
dc.setPenWidth(2);
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
var angle = (i / 10.0) * 360.0 - 90.0; // -90 to start at top
|
||||||
|
var angleRad = Math.toRadians(angle);
|
||||||
|
|
||||||
|
// Calculate tick mark positions
|
||||||
|
var tickOuterX = centerX + radius * Math.cos(angleRad);
|
||||||
|
var tickOuterY = centerY + radius * Math.sin(angleRad);
|
||||||
|
var tickInnerX = centerX + (radius - 15) * Math.cos(angleRad);
|
||||||
|
var tickInnerY = centerY + (radius - 15) * Math.sin(angleRad);
|
||||||
|
|
||||||
|
// Draw tick mark
|
||||||
|
dc.drawLine(tickOuterX, tickOuterY, tickInnerX, tickInnerY);
|
||||||
|
|
||||||
|
// Draw number
|
||||||
|
var numberX = centerX + (radius - 35) * Math.cos(angleRad);
|
||||||
|
var numberY = centerY + (radius - 35) * Math.sin(angleRad);
|
||||||
|
|
||||||
|
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
|
||||||
|
dc.drawText(
|
||||||
|
numberX,
|
||||||
|
numberY,
|
||||||
|
Graphics.FONT_MEDIUM,
|
||||||
|
i.toString(),
|
||||||
|
Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw center dot
|
||||||
|
dc.fillCircle(centerX, centerY, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw the hand pointing to current decimal time
|
||||||
|
function drawHand(dc, decimalTime) {
|
||||||
|
var width = dc.getWidth();
|
||||||
|
var height = dc.getHeight();
|
||||||
|
var centerX = width / 2;
|
||||||
|
var centerY = height / 2;
|
||||||
|
var radius = (width < height ? width : height) / 2 - 10;
|
||||||
|
|
||||||
|
// Calculate hand angle (0-10 maps to 0-360 degrees, starting at top)
|
||||||
|
var angle = (decimalTime / 10.0) * 360.0 - 90.0; // -90 to start at top
|
||||||
|
var angleRad = Math.toRadians(angle);
|
||||||
|
|
||||||
|
// Hand length (slightly shorter than radius to not overlap with numbers)
|
||||||
|
var handLength = radius - 50;
|
||||||
|
|
||||||
|
// Calculate hand tip position
|
||||||
|
var handTipX = centerX + handLength * Math.cos(angleRad);
|
||||||
|
var handTipY = centerY + handLength * Math.sin(angleRad);
|
||||||
|
|
||||||
|
// Calculate hand base positions (for a triangle/arrow shape)
|
||||||
|
var handWidth = 6;
|
||||||
|
var perpAngleRad1 = angleRad + Math.toRadians(90);
|
||||||
|
var perpAngleRad2 = angleRad - Math.toRadians(90);
|
||||||
|
|
||||||
|
var baseX1 = centerX + handWidth * Math.cos(perpAngleRad1);
|
||||||
|
var baseY1 = centerY + handWidth * Math.sin(perpAngleRad1);
|
||||||
|
var baseX2 = centerX + handWidth * Math.cos(perpAngleRad2);
|
||||||
|
var baseY2 = centerY + handWidth * Math.sin(perpAngleRad2);
|
||||||
|
|
||||||
|
// Draw the hand as a filled polygon
|
||||||
|
dc.setColor(Graphics.COLOR_RED, Graphics.COLOR_TRANSPARENT);
|
||||||
|
dc.fillPolygon([
|
||||||
|
[handTipX, handTipY],
|
||||||
|
[baseX1, baseY1],
|
||||||
|
[baseX2, baseY2]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw digital display of decimal time
|
||||||
|
function drawDigitalTime(dc, decimalTime) {
|
||||||
|
var width = dc.getWidth();
|
||||||
|
var height = dc.getHeight();
|
||||||
|
|
||||||
|
// Format decimal time to 2 decimal places
|
||||||
|
var timeString = decimalTime.format("%.2f");
|
||||||
|
|
||||||
|
// Draw at bottom center
|
||||||
|
dc.setColor(Graphics.COLOR_WHITE, Graphics.COLOR_TRANSPARENT);
|
||||||
|
dc.drawText(
|
||||||
|
width / 2,
|
||||||
|
height * 0.75,
|
||||||
|
Graphics.FONT_LARGE,
|
||||||
|
timeString,
|
||||||
|
Graphics.TEXT_JUSTIFY_CENTER | Graphics.TEXT_JUSTIFY_VCENTER
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user