import {LitElement, svg, SVGTemplateResult, unsafeCSS} from 'lit';
import componentStyle from './compass-flat.css?inline';
import {customElement, property, state} from 'lit/decorators.js';
import {Tickmark, TickmarkType} from '../watch-flat/tickmark-flat';
import '../watch-flat/watch-flat';
export enum LabelPosition {
top = -45,
bottom = 50,
}
export enum LabelStyle {
regular = 'var(--instrument-tick-mark-secondary-color)',
}
export interface Label {
x: number;
y: LabelPosition;
text: string;
}
/**
*
* @ignition-base-height: 170px
* @ignition-base-width: 512px
*/
@customElement('obc-compass-flat')
export class ObcCompassFlat extends LitElement {
@property({type: Boolean}) noPadding: boolean = true;
@property({type: Boolean}) FOVIndicator: boolean = false;
@property({type: Number}) padding: number = 16;
@property({type: Number}) heading = 0;
@property({type: Number}) courseOverGround = 0;
@property({type: Number}) tickInterval = 5;
@property({type: Number}) FOV = 45;
@property({type: Number}) minFOV = 45;
@property({type: Number}) maxFOV = 180;
@state() containerWidth = 0;
@state() maxContainerWidth = 0;
private resizeObserver: ResizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
// Made by chatGPT so that the text is inside the wrapper
this.maxContainerWidth = -125.36 + 3.79 * entry.contentRect.height;
this.containerWidth = Math.min(
entry.contentRect.width,
this.maxContainerWidth
);
}
});
override connectedCallback() {
super.connectedCallback();
this.resizeObserver.observe(this);
}
override disconnectedCallback() {
super.disconnectedCallback();
this.resizeObserver.unobserve(this);
}
generateLabels() {
if (this.containerWidth < 192) {
return [];
} else if (this.containerWidth <= 300) {
return [
{x: -180, y: LabelPosition.top, text: 'S'},
{x: -90, y: LabelPosition.top, text: 'W'},
{x: 0, y: LabelPosition.top, text: 'N'},
{x: 90, y: LabelPosition.top, text: 'E'},
{x: 180, y: LabelPosition.top, text: 'S'},
{x: 270, y: LabelPosition.top, text: 'W'},
{x: 360, y: LabelPosition.top, text: 'N'},
{x: 450, y: LabelPosition.top, text: 'E'},
{x: 540, y: LabelPosition.top, text: 'S'},
];
} else {
return [
{x: -180, y: LabelPosition.top, text: 'S'},
{x: -135, y: LabelPosition.top, text: 'SW'},
{x: -90, y: LabelPosition.top, text: 'W'},
{x: -45, y: LabelPosition.top, text: 'NW'},
{x: 0, y: LabelPosition.top, text: 'N'},
{x: 45, y: LabelPosition.top, text: 'NE'},
{x: 90, y: LabelPosition.top, text: 'E'},
{x: 135, y: LabelPosition.top, text: 'SE'},
{x: 180, y: LabelPosition.top, text: 'S'},
{x: 225, y: LabelPosition.top, text: 'SW'},
{x: 270, y: LabelPosition.top, text: 'W'},
{x: 315, y: LabelPosition.top, text: 'NW'},
{x: 360, y: LabelPosition.top, text: 'N'},
{x: 405, y: LabelPosition.top, text: 'NE'},
{x: 450, y: LabelPosition.top, text: 'E'},
{x: 495, y: LabelPosition.top, text: 'SE'},
{x: 540, y: LabelPosition.top, text: 'S'},
];
}
}
private generateIntervalTickmarks(scale: number): Tickmark[] {
const tickmarks: Tickmark[] = [];
let cardinalInterval = 90;
if (this.containerWidth > 300) {
cardinalInterval = 45;
} else if (this.containerWidth < 192) {
cardinalInterval = 0;
}
for (
let angle = -180;
angle < this.maxFOV * 3;
angle += this.tickInterval
) {
if (cardinalInterval !== 0 && angle % cardinalInterval === 0) {
continue;
}
tickmarks.push({angle: angle * scale, type: TickmarkType.secondary});
}
return tickmarks;
}
private generateCardinalTickmarks(
scale: number,
labels: Label[]
): Tickmark[] {
const tickmarks: Tickmark[] = [];
for (const label of labels) {
tickmarks.push({angle: label.x * scale, type: TickmarkType.main});
}
return tickmarks;
}
private generateTickmarks(scale: number, labels: Label[]): Tickmark[] {
return [
...this.generateCardinalTickmarks(scale, labels),
...this.generateIntervalTickmarks(scale),
];
}
private renderFOVIndicator(): SVGTemplateResult[] {
const indicators: SVGTemplateResult[] = [];
const maxAdjustment = 10;
const minContainerWidth = 300;
const maxContainerWidth = 512;
let yAdjustment = 0;
if (this.containerWidth < maxContainerWidth) {
const widthRange = maxContainerWidth - minContainerWidth;
const scaleFactor =
(maxContainerWidth - this.containerWidth) / widthRange;
yAdjustment = scaleFactor * maxAdjustment;
}
const y = LabelPosition.bottom + yAdjustment;
indicators.push(svg`