@geogirafe/lib-geoportal 1.1.0-dev.2438155631 → 1.1.0-dev.2438378072

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,9 +70,11 @@
70
70
  "Define time restriction on group": "Zeitliche Begrenzung für Gruppe definieren",
71
71
  "Define time restriction on layer": "Zeitliche Begrenzung für Layer definieren",
72
72
  "delete": "Löschen",
73
+ "Delete all shapes": "Alle Formen löschen",
73
74
  "Delete bookmark": "Lesezeichen löschen",
74
75
  "Delete Feature": "Funktion löschen",
75
76
  "Delete feature": "Objekt löschen",
77
+ "Delete Features": "Objekte löschen",
76
78
  "Delete shape": "Form löschen",
77
79
  "Delete Theme": "Thema löschen",
78
80
  "delete_help": "Profil-Linie löschen",
@@ -85,6 +87,7 @@
85
87
  "Do you want to delete this theme?": "Möchten Sie dieses Thema löschen?",
86
88
  "Do you want to logout ?": "Möchten Sie sich abmelden?",
87
89
  "Do you want to remove \"${feature.name}\" ?": "Möchten Sie \"${feature.name}\" entfernen?",
90
+ "Do you want to remove all features?": "Möchten Sie alle Objekte entfernen?",
88
91
  "Documentation": "Dokumentation",
89
92
  "does not contain": "enthält nicht",
90
93
  "does not equal": "ungleich",
@@ -102,6 +105,7 @@
102
105
  "Draw polygons": "Polygone zeichnen",
103
106
  "draw_profile": "Profil-Linie zeichnen",
104
107
  "draw_profile_help": "Profil-Linien-Zeichnen auf der Karte umschalten",
108
+ "Drawing List": "Zeichnungsliste",
105
109
  "drawing-panel": "Zeichnen & messen",
106
110
  "drawingFillColor": "Zeichnen Füllfarbe",
107
111
  "Drawings": "Zeichnungen",
@@ -142,7 +146,10 @@
142
146
  "Filter layer": "Layer filtern",
143
147
  "Filter layer tree...": "Layerliste filtern...",
144
148
  "Filtering deactivated: layers in layergroup don't have identical attributes.": "Filterung deaktiviert: Layer in der Layergruppe haben nicht identische Attribute.",
149
+ "Fix height to": "Höhe festlegen auf",
145
150
  "Fix length to": "Länge festlegen auf",
151
+ "Fix side length to": "Seitenlänge festlegen auf",
152
+ "Fix width to": "Breite festlegen auf",
146
153
  "Font": "Schriftart",
147
154
  "Format": "Format",
148
155
  "fr": "Französisch",
@@ -378,6 +385,7 @@
378
385
  "selectStrokeColor": "Auswahl Strichfarbe",
379
386
  "Send": "Senden",
380
387
  "Send message": "Nachricht senden",
388
+ "Settings": "Einstellungen",
381
389
  "Shadows": "Schatten",
382
390
  "Share this map": "Diese Karte teilen",
383
391
  "share-panel": "Karte teilen oder einbetten",
@@ -73,6 +73,8 @@
73
73
  "Delete bookmark": "Delete bookmark",
74
74
  "Delete Feature": "Delete Feature",
75
75
  "Delete feature": "Delete feature",
76
+ "Delete Features": "Delete Features",
77
+ "Delete all shapes": "Delete all shapes",
76
78
  "Delete shape": "Delete shape",
77
79
  "Delete Theme": "Delete Theme",
78
80
  "delete_help": "Delete profile line",
@@ -85,6 +87,7 @@
85
87
  "Do you want to delete this theme?": "Do you want to delete this theme?",
86
88
  "Do you want to logout ?": "Do you want to logout?",
87
89
  "Do you want to remove \"${feature.name}\" ?": "Do you want to remove \"${feature.name}\"?",
90
+ "Do you want to remove all features?": "Do you want to remove all features?",
88
91
  "Documentation": "Documentation",
89
92
  "does not contain": "does not contain",
90
93
  "does not equal": "does not equal",
@@ -102,6 +105,7 @@
102
105
  "Draw polygons": "Draw polygons",
103
106
  "draw_profile": "Draw profile line",
104
107
  "draw_profile_help": "Toggle profile line drawing on map",
108
+ "Drawing List": "Drawings List",
105
109
  "drawing-panel": "Draw & measure",
106
110
  "drawingFillColor": "Drawing fill color",
107
111
  "Drawings": "Drawings",
@@ -143,7 +147,10 @@
143
147
  "Filter layer": "Filter layer",
144
148
  "Filter layer tree...": "Filter layer tree...",
145
149
  "Filtering deactivated: layers in layergroup don't have identical attributes.": "Filtering deactivated: layers in layergroup don't have identical attributes.",
150
+ "Fix height to": "Fix height to",
146
151
  "Fix length to": "Fix length to",
152
+ "Fix side length to": "Fix side length to",
153
+ "Fix width to": "Fix width to",
147
154
  "Font": "Font",
148
155
  "Format": "Format",
149
156
  "fr": "French",
@@ -379,6 +386,7 @@
379
386
  "selectStrokeColor": "Selection stroke color",
380
387
  "Send": "Send",
381
388
  "Send message": "Send message",
389
+ "Settings": "Settings",
382
390
  "Shadows": "Shadows",
383
391
  "Share this map": "Share this map",
384
392
  "share-panel": "Share or embed map",
@@ -70,9 +70,11 @@
70
70
  "Define time restriction on group": "Définir la restriction temporelle pour le groupe",
71
71
  "Define time restriction on layer": "Définir la restriction temporelle sur la couche",
72
72
  "delete": "Supprimer",
73
+ "Delete all shapes": "Supprimer toutes les formes",
73
74
  "Delete bookmark": "Supprimer le favori",
74
75
  "Delete Feature": "Supprimer la fonctionnalité",
75
76
  "Delete feature": "Suppression de l'entité",
77
+ "Delete Features": "Supprimer les objets",
76
78
  "Delete shape": "Supprimer la forme",
77
79
  "Delete Theme": "Supprimer le thème",
78
80
  "delete_help": "Supprimer la ligne de profil",
@@ -85,6 +87,7 @@
85
87
  "Do you want to delete this theme?": "Voulez-vous supprimer ce thème ?",
86
88
  "Do you want to logout ?": "Voulez-vous vous déconnecter ?",
87
89
  "Do you want to remove \"${feature.name}\" ?": "Voulez-vous supprimer \"${feature.name}\" ?",
90
+ "Do you want to remove all features?": "Voulez-vous supprimer tous les objets ?",
88
91
  "Documentation": "Documentation",
89
92
  "does not contain": "ne contient pas",
90
93
  "does not equal": "n'est pas égal à",
@@ -102,6 +105,7 @@
102
105
  "Draw polygons": "Tracer des polygones",
103
106
  "draw_profile": "Dessiner",
104
107
  "draw_profile_help": "Activer/désactiver le dessin de la ligne de profil sur la carte",
108
+ "Drawing List": "Liste des dessins",
105
109
  "drawing-panel": "Dessiner & mesurer",
106
110
  "drawingFillColor": "Couleur de remplissage du dessin",
107
111
  "Drawings": "Dessins",
@@ -142,7 +146,10 @@
142
146
  "Filter layer": "Filtrer la couche",
143
147
  "Filter layer tree...": "Filtrer les couches...",
144
148
  "Filtering deactivated: layers in layergroup don't have identical attributes.": "Filtrage désactivé : les couches dans le groupe de couches n'ont pas d'attributs identiques.",
149
+ "Fix height to": "Fixer la hauteur à",
145
150
  "Fix length to": "Fixer la longueur à",
151
+ "Fix side length to": "Fixer la longueur du côté à",
152
+ "Fix width to": "Fixer la largeur à",
146
153
  "Font": "Police",
147
154
  "Format": "Format",
148
155
  "fr": "Français",
@@ -378,6 +385,7 @@
378
385
  "selectStrokeColor": "Couleur du trait de sélection",
379
386
  "Send": "Envoyer",
380
387
  "Send message": "Envoyer un message",
388
+ "Settings": "Paramètres",
381
389
  "Shadows": "Ombres",
382
390
  "Share this map": "Partager cette carte",
383
391
  "share-panel": "Partager ou intégrer la carte",
@@ -70,9 +70,11 @@
70
70
  "Define time restriction on group": "Definire la restrizione temporale del gruppo",
71
71
  "Define time restriction on layer": "Definire la restrizione temporale del livello",
72
72
  "delete": "Elimina",
73
+ "Delete all shapes": "Elimina tutte le forme",
73
74
  "Delete bookmark": "Elimina segnalibro",
74
75
  "Delete Feature": "Elimina funzionalità",
75
76
  "Delete feature": "Eliminare l'elemento",
77
+ "Delete Features": "Elimina oggetti",
76
78
  "Delete shape": "Elimina forma",
77
79
  "Delete Theme": "Elimina tema",
78
80
  "delete_help": "Elimina la linea di profilo",
@@ -85,6 +87,7 @@
85
87
  "Do you want to delete this theme?": "Vuoi eliminare questo tema?",
86
88
  "Do you want to logout ?": "Vuoi disconnetterti?",
87
89
  "Do you want to remove \"${feature.name}\" ?": "Vuoi rimuovere \"${feature.name}\"?",
90
+ "Do you want to remove all features?": "Vuoi rimuovere tutti gli oggetti?",
88
91
  "Documentation": "Documentazione",
89
92
  "does not contain": "non contiene",
90
93
  "does not equal": "diverso da",
@@ -102,6 +105,7 @@
102
105
  "Draw polygons": "Disegnare un poligono",
103
106
  "draw_profile": "Disegna linea di profilo",
104
107
  "draw_profile_help": "Attiva/disattiva il disegno della linea di profilo sulla mappa",
108
+ "Drawing List": "Elenco dei disegni",
105
109
  "drawing-panel": "Disegna e misura",
106
110
  "drawingFillColor": "Colore di riempimento del disegno",
107
111
  "Drawings": "Disegni",
@@ -142,7 +146,10 @@
142
146
  "Filter layer": "Filtra layer",
143
147
  "Filter layer tree...": "Albero dei livelli di filtraggio...",
144
148
  "Filtering deactivated: layers in layergroup don't have identical attributes.": "Filtro disattivato: i layer nel gruppo non hanno attributi identici.",
149
+ "Fix height to": "Fissa l’altezza a",
145
150
  "Fix length to": "Fissa la lunghezza a",
151
+ "Fix side length to": "Fissare la lunghezza del lato a",
152
+ "Fix width to": "Fissa la larghezza a",
146
153
  "Font": "Carattere",
147
154
  "Format": "Formato",
148
155
  "fr": "Francese",
@@ -378,6 +385,7 @@
378
385
  "selectStrokeColor": "Colore del tratto di selezione",
379
386
  "Send": "Invia",
380
387
  "Send message": "Invia messaggio",
388
+ "Settings": "Impostazioni",
381
389
  "Shadows": "Ombre",
382
390
  "Share this map": "Condividi questa mappa",
383
391
  "share-panel": "Condividi o incorpora la mappa",
@@ -9,7 +9,7 @@ declare abstract class GirafeHTMLElement extends HTMLElement {
9
9
  protected template: Hole | (() => Hole);
10
10
  readonly name: string;
11
11
  protected shadow: ShadowRoot;
12
- private displayStyle?;
12
+ protected displayStyle?: string;
13
13
  private timeoutId?;
14
14
  protected rendered: boolean;
15
15
  private readonly callbacks;
File without changes
@@ -11,13 +11,13 @@ export default class CesiumDrawing {
11
11
  scene: Cesium.Scene | undefined;
12
12
  handler: Cesium.ScreenSpaceEventHandler | undefined;
13
13
  entities: Cesium.EntityCollection | undefined;
14
- fixedLength: number;
14
+ fixedLineLength: number;
15
15
  private readonly context;
16
16
  private get state();
17
17
  private get drawingState();
18
18
  private get config();
19
19
  constructor(map: MapComponent, toolName: string, context: IGirafeContext);
20
- setFixedLength(length: number): void;
20
+ setFixedLineLength(length: number): void;
21
21
  activateTool(tool: DrawingShape): void;
22
22
  deactivateTool(): void;
23
23
  pickOnGlobe(position: Cartesian2): Cesium.Cartesian3 | undefined;
@@ -13,7 +13,7 @@ export default class CesiumDrawing {
13
13
  scene = undefined;
14
14
  handler = undefined;
15
15
  entities = undefined;
16
- fixedLength = 0;
16
+ fixedLineLength = 0;
17
17
  context;
18
18
  get state() {
19
19
  return this.context.stateManager.state;
@@ -36,8 +36,8 @@ export default class CesiumDrawing {
36
36
  }
37
37
  });
38
38
  }
39
- setFixedLength(length) {
40
- this.fixedLength = Number.isNaN(length) ? 0 : length;
39
+ setFixedLineLength(length) {
40
+ this.fixedLineLength = Number.isNaN(length) ? 0 : length;
41
41
  }
42
42
  activateTool(tool) {
43
43
  if (!this.canExecute('globe.draw')) {
@@ -124,7 +124,7 @@ export default class CesiumDrawing {
124
124
  this.activeShapePoints = [];
125
125
  }
126
126
  fixLastLength(tool, length, coord) {
127
- if (this.fixedLength > 0 && tool != DrawingShape.Rectangle) {
127
+ if (this.fixedLineLength > 0 && tool != DrawingShape.Rectangle) {
128
128
  const factor = tool == DrawingShape.Square ? Math.SQRT2 / 2 : 1;
129
129
  const pointCarto = new EllipsoidGeodesic(Cartographic.fromCartesian(coord[coord.length - 2]), Cartographic.fromCartesian(coord[coord.length - 1])).interpolateUsingSurfaceDistance(length * factor);
130
130
  coord[coord.length - 1] = Cartographic.toCartesian(pointCarto);
@@ -140,7 +140,7 @@ export default class CesiumDrawing {
140
140
  }
141
141
  else {
142
142
  this.activeShapePoints[this.activeShapePoints.length - 1] = newPosition;
143
- this.fixLastLength(tool, this.fixedLength, this.activeShapePoints);
143
+ this.fixLastLength(tool, this.fixedLineLength, this.activeShapePoints);
144
144
  }
145
145
  this.activeShapes.forEach((e) => this.entities.remove(e));
146
146
  this.activeShapes = this.getShapes(tool, this.activeShapePoints, new DrawingFeature(tool, this.drawingState, this.config.drawing));
@@ -7,11 +7,11 @@ export default class DrawingComponentMobile extends DrawingComponent {
7
7
  return uHtml `<style>
8
8
  *{font-family:Arial,sans-serif}.hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height)/1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad2);background-color:var(--text-color-grad2);color:var(--bkg-color)}.gg-button:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3;border:none}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height)/1.2);min-height:calc(var(--app-standard-height)/1.2);max-height:calc(var(--app-standard-height)/1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height)/2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height)/2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height)/2);min-height:calc(var(--app-standard-height)/2);max-height:calc(var(--app-standard-height)/2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height)/3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height)/3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover,.gg-select:hover,.gg-input:hover,.gg-textarea:hover,.gg-icon-button:hover{background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height)/2);height:calc(var(--app-standard-height)/2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}
9
9
  </style><style>
10
- input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var(--bkg-color-input);padding-right:0}input:focus{border:1px solid var(--lt-color-gray-900)}button{border:solid 1px var(--bkg-color);color:var(--text-color);background-color:var(--bkg-color);cursor:pointer;padding:0}button:hover{border:solid 1px var(--text-color-grad2)}button.selected{border:solid 1px var(--text-color-grad2);background-color:var(--bkg-color-grad1);color:var(--bkg-color)}#toolbar{flex-wrap:wrap;display:flex}.label-container{flex-grow:1}.text-end{text-align:end}.icon{width:1.2rem;height:1.2rem;fill:var(--text-color);flex-shrink:0;margin:3px}.icon:hover{fill:var(--text-color-grad2)}.gg-icon-button:hover{border:none}.colorPicker{border:1px solid var(--text-color);border-radius:5px}.picker_wrapper{transform:translate(-250px)}.picker_arrow{transform:translate(200px)rotate(90deg)scaleX(-1)!important}.picker_wrapper,.picker_arrow:after,.picker_arrow:before{background-color:var(--bkg-color)!important}.picker_wrapper,.picker_arrow:before{box-shadow:0 0 10px 1px var(--text-color-grad1)!important}button:disabled,input:disabled,.disabled{pointer-events:none;opacity:.5}fieldset.field-wrapper{border:0;margin:0;padding:0}#panel{height:100%;color:var(--text-color);flex-direction:column;display:flex}#panel>div{padding:1rem}.toolParameters{grid-template-columns:auto auto 60px auto;justify-content:left;align-items:center;margin-top:10px;display:grid}.toolParameters>label{padding:0 5px}#drawingListContainer{flex-grow:1;overflow:hidden auto}#drawingList{flex-flow:column;gap:.15rem;display:flex}#drawingList .girafe{border:solid 1px var(--text-color);flex-wrap:wrap;align-items:center;padding:.3rem;display:flex;position:relative}#drawingList .girafe span{flex-grow:1;padding-left:5px}#options{box-shadow:0px -2px 3px -1px var(--text-color-grad1);z-index:100;flex-direction:column;display:flex;position:relative}#optionsTitle{text-align:center;margin-bottom:20px;font-size:1.2rem}#options hr{width:100%;margin:8px 0}#optionsTextLines,#optionsColorLine,#optionsLineLines{align-items:center;display:grid}#optionsText{margin:auto}#optionsTextLines{grid-template-columns:2fr 2fr 1fr 4em 1fr 1fr}#optionsTextLines button:hover{border:none}#optionsColor,#optionsLine,#optionsExport,#optionsArrow{margin:auto}#optionsColorLine{display:flex}#optionsColorLine>div{align-items:center;width:100%;display:flex}#optionsLineLines,#optionsArrowStyle{grid-template-columns:3fr 4em 1fr auto}#optionsExportLine{grid-template-columns:60px 60px 45px 45px;gap:.2rem;display:flex}
10
+ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var(--bkg-color-input);padding-right:0}input:focus{border:1px solid var(--lt-color-gray-900)}button{border:solid 1px var(--bkg-color);color:var(--text-color);background-color:var(--bkg-color);cursor:pointer;padding:0}button:hover{border:solid 1px var(--text-color-grad2)}button.selected{border:solid 1px var(--text-color-grad2);background-color:var(--bkg-color-grad1);color:var(--bkg-color)}#toolbar{flex-wrap:wrap;display:flex}.label-container{flex-grow:1}.text-end{text-align:end}.icon{width:1.2rem;height:1.2rem;fill:var(--text-color);flex-shrink:0;margin:3px}.icon:hover{fill:var(--text-color-grad2)}.gg-icon-button:hover{border:none}.colorPicker{border:1px solid var(--text-color);border-radius:5px}.picker_wrapper{transform:translate(-250px)}.picker_arrow{transform:translate(200px)rotate(90deg)scaleX(-1)!important}.picker_wrapper,.picker_arrow:after,.picker_arrow:before{background-color:var(--bkg-color)!important}.picker_wrapper,.picker_arrow:before{box-shadow:0 0 10px 1px var(--text-color-grad1)!important}button:disabled,input:disabled,.disabled{pointer-events:none;opacity:.5}fieldset.field-wrapper{border:0;margin:0;padding:0}#panel{height:100%;color:var(--text-color);flex-direction:column;display:flex}#panel>div{padding:1rem}#toolParametersContainer{& .title{margin-top:.5rem;margin-bottom:.75rem;display:inline-block}}.toolParameters{flex-direction:column;justify-content:left;row-gap:.25rem;display:flex}.toolParameters>label{padding:0 5px}#drawingListContainer{flex-grow:1;overflow:hidden auto;padding-top:0!important;& .titleContainer{margin-bottom:1rem;display:flex;& .title{flex-grow:1;align-items:center;display:flex}}}#drawingList{flex-flow:column;gap:.15rem;display:flex}#drawingList .girafe{border:solid 1px var(--text-color);flex-wrap:wrap;align-items:center;padding:.3rem;display:flex;position:relative}#drawingList .girafe span{flex-grow:1;padding-left:5px}#options{box-shadow:0px -2px 3px -1px var(--text-color-grad1);z-index:100;flex-direction:column;display:flex;position:relative}#optionsTitle{text-align:center;margin-bottom:20px;font-size:1.2rem}#options hr{width:100%;margin:8px 0}#optionsTextLines,#optionsColorLine,#optionsLineLines{align-items:center;display:grid}#optionsText{margin:auto}#optionsTextLines{grid-template-columns:2fr 2fr 1fr 4em 1fr 1fr}#optionsTextLines button:hover{border:none}#optionsColor,#optionsLine,#optionsExport,#optionsArrow{margin:auto}#optionsColorLine{display:flex}#optionsColorLine>div{align-items:center;width:100%;display:flex}#optionsLineLines,#optionsArrowStyle{grid-template-columns:3fr 4em 1fr auto}#optionsExportLine{grid-template-columns:60px 60px 45px 45px;gap:.2rem;display:flex}
11
11
  </style><style>
12
12
  button.selected{background-color:#daebff!important;border:1px solid #54a4ff!important}#toolbar{box-sizing:border-box;grid-template-columns:repeat(5,1fr);gap:20px;width:100%;display:grid}#toolbar>button{box-sizing:border-box;filter:drop-shadow(0 4px 7px #0004382c);background-color:#fff;border-radius:8px;padding:10px}#toolbar>button>img{opacity:.7;width:100%}.icon{width:1.5rem;height:1.5rem}.gg-icon-button:hover{background-color:#0000}#panel{font-size:1.5em}#drawingList{gap:10px}#drawingList .girafe{filter:drop-shadow(0 4px 7px #0004381c);background:#fff;border:none;border-radius:8px;padding:10px}#optionsTitle{text-align:center;filter:drop-shadow(0 4px 7px #0004381c);color:#4553ff;border-radius:8px;width:100%;margin-bottom:20px;padding:10px;font-size:1.6rem}.gg-input:hover{filter:drop-shadow(0 4px 7px #4c58ff70);background-color:#fff}#optionsColorLine{flex-direction:column;display:flex}#optionsColorLine>div{text-align:end;width:100%}.selectable-label{font-size:1.3em}#optionsNameFontSize,#optionsMeasuresFontSize,#optionsStrokeWidth,#line-style,#arrow-style,#arrow-position{text-align:right;border:1px solid #e3e3e3;padding:1px;font-size:1em}.popup.popup_top{translate:15px -15px}#optionsExportLine{display:none}
13
13
  </style>
14
- <link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="panel"><div><div id="toolbar"><button id="disable" tip="Disable drawing" class="gg-icon-button gg-medium"><img alt="select icon" src="icons/arrow.svg"></button> <button id="point" tip="Point" class="gg-icon-button gg-medium"><img alt="point icon" src="icons/point.svg"></button> <button id="line" tip="Line" class="gg-icon-button gg-medium"><img alt="polyline icon" src="icons/polyline.svg"></button> <button id="polygon" tip="Polygon" class="gg-icon-button gg-medium"><img alt="polygon icon" src="icons/polygon.svg"></button> <button id="square" tip="Square" class="gg-icon-button gg-medium"><img alt="square icon" src="icons/square.svg"></button> <button id="rectangle" tip="Rectangle" class="gg-icon-button gg-medium"><img alt="rectangle icon" src="icons/rectangle.svg"></button> <button id="circle" tip="Circle" class="gg-icon-button gg-medium"><img alt="circle icon" src="icons/circle.svg"></button> <button id="freeline" tip="Freehand line" class="gg-icon-button gg-medium"><img alt="polyline-free icon" src="icons/polyline-free.svg"></button> <button id="freepolygon" tip="Freehand polygon" class="gg-icon-button gg-medium"><img alt="polygon-free icon" src="icons/polygon-free.svg"></button></div><div class="toolParameters"><button id="fixedLengthEnabled" class="gg-icon-button icon" disabled="${!this.fixedLengthOptionAllowed()}" onclick="${() => this.onToggleFixedLength()}">${this.htmlUnsafe(this.fixedLengthEnabled ? this.checkedIcon : this.noCheckedIcon)}</button> <label class="${this.fixedLengthEnabled && this.fixedLengthOptionAllowed() ? 'gg-label' : 'gg-label disabled'}" for="fixedLengthValue" i18n="Fix length to">Fix length to</label> <input class="gg-input" disabled="${!(this.fixedLengthEnabled && this.fixedLengthOptionAllowed())}" type="number" id="fixedLengthValue"> <label class="${this.fixedLengthEnabled && this.fixedLengthOptionAllowed() ? 'gg-label' : 'gg-label disabled'}" disabled="${!(this.fixedLengthEnabled && this.fixedLengthOptionAllowed())}" for="fixedLengthValue" i18n="meters">meters</label></div></div><div id="drawingListContainer"><div id="drawingList">${this.drawingState.features.map(feature => uHtmlFor(feature, feature.id) `<div id="${'f-' + feature.id}" class="girafe"><button id="${'f-select-' + feature.id}" class="gg-icon-button gg-small" tip="Select to change appearance" onclick="${() => this.onToggleFeatureSelection(feature)}"><div class="icon">${this.htmlUnsafe(feature.selected ? this.checkedIcon : this.noCheckedIcon)}</div></button><div class="label-container"><button class="${feature.selected ? 'selectable-label gg-icon-button gg-small gg-selected' : 'selectable-label gg-icon-button gg-small gg-opacity'}" onclick="${() => this.onToggleFeatureSelection(feature)}"><span id="${'f-name-' + feature.id}">${feature.name}</span></button></div><button class="gg-icon-button icon" tip="Center on shape" onclick="${() => this.olDrawing.centerViewOnFeature(feature)}">${this.htmlUnsafe(this.locateIcon)}</button> <button class="gg-icon-button icon" tip="Delete shape" onclick="${() => this.deleteFeature(feature)}">${this.htmlUnsafe(this.trashIcon)}</button></div>`)}</div></div><div id="options" class="${this.selectedFeatures.length > 0 ? '' : 'disabled'}"><fieldset class="field-wrapper" disabled="${this.selectedFeatures.length <= 0}"><input id="optionsTitle" value="${this.getOptionsTitle()}" class="gg-input" disabled="${this.selectedFeatures.length > 1}"><div id="optionsText"><div id="optionsTextLines"><span i18n="Name">Name</span> <button class="gg-icon-button icon" id="visibleIconName" tip="Show or hide shape name" onclick="${() => this.toggleNameVisibility()}">${this.htmlUnsafe(this.isDisplayNameEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsNameFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.nameFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="nameColorPicker"></button> <span i18n="Measures">Measures</span> <button class="gg-icon-button icon" id="visibleIconMeasure" tip="Show or hide measure information" onclick="${() => this.toggleMeasureVisibility()}">${this.htmlUnsafe(this.isDisplayMeasureEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsMeasuresFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.measureFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="measureColorPicker"></button></div></div><hr><div id="optionsColor"><div id="optionsColorLine"><div><span class="text-end" i18n="Stroke color">Stroke color</span> <button class="icon colorPicker" id="strokePicker"></button></div><div><span class="${this.isFillColorEnabled() ? 'text-end' : 'text-end disabled'}" id="fillPickerSpan" i18n="Fill color">Fill color</span> <button class="icon colorPicker" disabled="${!this.isFillColorEnabled()}" id="fillPicker"></button></div></div></div><hr><div id="optionsLine"><div id="optionsLineLines"><span i18n="Line width">Line width</span> <input id="optionsStrokeWidth" type="number" class="gg-input" min="1" value="${this.selectedFeatures[0]?.strokeWidth}" oninput="${() => this.onOptionsChange()}"> <span>px</span> <select id="line-style" class="gg-select" onchange="${() => this.onOptionsChange()}">${Object.entries(this.lineStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.lineStroke === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsArrow"><div class="${this.isLineStyleEnabled() ? '' : 'disabled'}" id="optionsArrowStyles"><span i18n="Arrows style">Arrows style</span> <select id="arrow-style" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowStyle === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select> <select id="arrow-position" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowPositions).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowPosition === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsExport"><div id="optionsExportLine"><label for="export" class="gg-label" i18n="Export">Export</label> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('geojson')}">GeoJson</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('kml')}">KML</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('gpx')}">GPX</button></div></div></fieldset></div></div>`;
14
+ <link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="panel"><div><div id="toolbar"><button id="disable" tip="Disable drawing" class="gg-icon-button gg-medium"><img alt="select icon" src="icons/arrow.svg"></button> <button id="point" tip="Point" class="gg-icon-button gg-medium"><img alt="point icon" src="icons/point.svg"></button> <button id="line" tip="Line" class="gg-icon-button gg-medium"><img alt="polyline icon" src="icons/polyline.svg"></button> <button id="polygon" tip="Polygon" class="gg-icon-button gg-medium"><img alt="polygon icon" src="icons/polygon.svg"></button> <button id="square" tip="Square" class="gg-icon-button gg-medium"><img alt="square icon" src="icons/square.svg"></button> <button id="rectangle" tip="Rectangle" class="gg-icon-button gg-medium"><img alt="rectangle icon" src="icons/rectangle.svg"></button> <button id="circle" tip="Circle" class="gg-icon-button gg-medium"><img alt="circle icon" src="icons/circle.svg"></button> <button id="freeline" tip="Freehand line" class="gg-icon-button gg-medium"><img alt="polyline-free icon" src="icons/polyline-free.svg"></button> <button id="freepolygon" tip="Freehand polygon" class="gg-icon-button gg-medium"><img alt="polygon-free icon" src="icons/polygon-free.svg"></button></div><div id="toolParametersContainer"><span i18n="Settings" class="title"></span><div class="toolParameters" data-tool="Polyline,Polygon"><girafe-fixed-dimension dimensionname="length" dimension="length" id="fixedLineLength" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension></div><div class="toolParameters" data-tool="Square"><girafe-fixed-dimension dimensionname="side length" dimension="side" id="fixedSquareSide" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension></div><div class="toolParameters" data-tool="Rectangle"><girafe-fixed-dimension dimensionname="width" dimension="width" id="fixedRectangleWidth" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension><girafe-fixed-dimension dimensionname="height" dimension="height" id="fixedRectangleHeight" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension></div></div></div><div id="drawingListContainer"><div class="titleContainer"><span i18n="Drawing List" class="title"></span> <button class="gg-icon-button icon" tip="Delete all shapes" onclick="${() => this.deleteAllFeatures()}" ?disabled="${this.drawingState.features.length === 0}">${this.htmlUnsafe(this.trashIcon)}</button></div><div id="drawingList">${this.drawingState.features.map(feature => uHtmlFor(feature, feature.id) `<div id="${'f-' + feature.id}" class="girafe"><button id="${'f-select-' + feature.id}" class="gg-icon-button gg-small" tip="Select to change appearance" onclick="${() => this.onToggleFeatureSelection(feature)}"><div class="icon">${this.htmlUnsafe(feature.selected ? this.checkedIcon : this.noCheckedIcon)}</div></button><div class="label-container"><button class="${feature.selected ? 'selectable-label gg-icon-button gg-small gg-selected' : 'selectable-label gg-icon-button gg-small gg-opacity'}" onclick="${() => this.onToggleFeatureSelection(feature)}"><span id="${'f-name-' + feature.id}">${feature.name}</span></button></div><button class="gg-icon-button icon" tip="Center on shape" onclick="${() => this.olDrawing.centerViewOnFeature(feature)}">${this.htmlUnsafe(this.locateIcon)}</button> <button class="gg-icon-button icon" tip="Delete shape" onclick="${() => this.deleteFeature(feature)}">${this.htmlUnsafe(this.trashIcon)}</button></div>`)}</div></div><div id="options" class="${this.selectedFeatures.length > 0 ? '' : 'disabled'}"><fieldset class="field-wrapper" disabled="${this.selectedFeatures.length <= 0}"><input id="optionsTitle" value="${this.getOptionsTitle()}" class="gg-input" disabled="${this.selectedFeatures.length > 1}"><div id="optionsText"><div id="optionsTextLines"><span i18n="Name">Name</span> <button class="gg-icon-button icon" id="visibleIconName" tip="Show or hide shape name" onclick="${() => this.toggleNameVisibility()}">${this.htmlUnsafe(this.isDisplayNameEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsNameFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.nameFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="nameColorPicker"></button> <span i18n="Measures">Measures</span> <button class="gg-icon-button icon" id="visibleIconMeasure" tip="Show or hide measure information" onclick="${() => this.toggleMeasureVisibility()}">${this.htmlUnsafe(this.isDisplayMeasureEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsMeasuresFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.measureFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="measureColorPicker"></button></div></div><hr><div id="optionsColor"><div id="optionsColorLine"><div><span class="text-end" i18n="Stroke color">Stroke color</span> <button class="icon colorPicker" id="strokePicker"></button></div><div><span class="${this.isFillColorEnabled() ? 'text-end' : 'text-end disabled'}" id="fillPickerSpan" i18n="Fill color">Fill color</span> <button class="icon colorPicker" disabled="${!this.isFillColorEnabled()}" id="fillPicker"></button></div></div></div><hr><div id="optionsLine"><div id="optionsLineLines"><span i18n="Line width">Line width</span> <input id="optionsStrokeWidth" type="number" class="gg-input" min="1" value="${this.selectedFeatures[0]?.strokeWidth}" oninput="${() => this.onOptionsChange()}"> <span>px</span> <select id="line-style" class="gg-select" onchange="${() => this.onOptionsChange()}">${Object.entries(this.lineStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.lineStroke === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsArrow"><div class="${this.isLineStyleEnabled() ? '' : 'disabled'}" id="optionsArrowStyles"><span i18n="Arrows style">Arrows style</span> <select id="arrow-style" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowStyle === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select> <select id="arrow-position" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowPositions).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowPosition === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsExport"><div id="optionsExportLine"><label for="export" class="gg-label" i18n="Export">Export</label> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('geojson')}">GeoJson</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('kml')}">KML</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('gpx')}">GPX</button></div></div></fieldset></div></div>`;
15
15
  };
16
16
  constructor() {
17
17
  super('drawing-mobile');
@@ -1,5 +1,5 @@
1
1
  import { Color } from 'vanilla-picker';
2
- import DrawingFeature, { DrawingState, DrawingShape, ArrowStyle, ArrowPosition } from './drawingFeature.js';
2
+ import DrawingFeature, { ArrowPosition, ArrowStyle, DrawingShape, DrawingState } from './drawingFeature.js';
3
3
  import OlDrawing from './olDrawing.js';
4
4
  import CesiumDrawing from './cesiumDrawing.js';
5
5
  import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
@@ -42,24 +42,25 @@ export default class DrawingComponent extends GirafeHTMLElement implements IGira
42
42
  unregisterEvents(): void;
43
43
  addColorPicker(id: string, set: (c: Color) => unknown, get: () => string): void;
44
44
  setTool(tool?: DrawingShape | null): void;
45
- fixedLengthOptionAllowed(): boolean;
45
+ showToolParameters(tool?: DrawingShape | null): void;
46
+ protected fixedDimensionValueChangedHandler(e: CustomEvent): void;
46
47
  protected connectedCallback(): void;
47
48
  togglePanel(visible: boolean): void;
48
49
  get selectedFeatures(): DrawingFeature[];
49
50
  deselectAllFeatures(): void;
50
51
  onFeaturesChanged(oldFeatures: DrawingFeature[], newFeatures: DrawingFeature[]): void;
51
52
  onProjectionChanged(oldProj: string, newProj: string): void;
52
- onToggleBatchMode(): void;
53
- onToggleFixedLength(): void;
53
+ protected onToggleBatchMode(): void;
54
54
  onToggleFeatureSelection(feature: DrawingFeature): void;
55
55
  activateLayerInTreeAndMap(layerName?: string): void;
56
56
  deactivateLayerInTreeAnMap(): void;
57
- getOptionsTitle(): string;
58
- isDisplayNameEnabled(): boolean;
59
- isDisplayMeasureEnabled(): boolean;
60
- isLineStyleEnabled(): boolean;
61
- isFillColorEnabled(): boolean;
57
+ protected getOptionsTitle(): string;
58
+ protected isDisplayNameEnabled(): boolean;
59
+ protected isDisplayMeasureEnabled(): boolean;
60
+ protected isLineStyleEnabled(): boolean;
61
+ protected isFillColorEnabled(): boolean;
62
62
  deleteFeature(feature: DrawingFeature): Promise<void>;
63
+ deleteAllFeatures(): Promise<void>;
63
64
  onOptionsChange(): void;
64
65
  onArrowsChange(): void;
65
66
  toggleNameVisibility(): void;
@@ -1,10 +1,16 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
1
7
  import { htmlFor as uHtmlFor } from 'uhtml/keyed';
2
8
  import { html as uHtml } from 'uhtml';
3
9
  import { v4 as uuidv4 } from 'uuid';
4
10
  import DrawingFeature, { DrawingShape } from './drawingFeature.js';
5
11
  import OlDrawing from './olDrawing.js';
6
12
  import CesiumDrawing from './cesiumDrawing.js';
7
- import { KML, GeoJSON, GPX } from 'ol/format.js';
13
+ import { GeoJSON, GPX, KML } from 'ol/format.js';
8
14
  import { Polygon } from 'ol/geom.js';
9
15
  import Feature from 'ol/Feature.js';
10
16
  import GirafeHTMLElement from '../../base/GirafeHTMLElement.js';
@@ -18,14 +24,15 @@ import locateIcon from './assets/locate.svg?raw';
18
24
  import visibleIcon from './assets/visible.svg?raw';
19
25
  import notVisibleIcon from './assets/notVisible.svg?raw';
20
26
  import LayerDrawing from '../../models/layers/layerdrawing.js';
27
+ import { UsedInTemplateOnly } from '../../decorators.js';
21
28
  export default class DrawingComponent extends GirafeHTMLElement {
22
29
  template = () => {
23
30
  return uHtml `<style>
24
31
  *{font-family:Arial,sans-serif}.hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height)/1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad2);background-color:var(--text-color-grad2);color:var(--bkg-color)}.gg-button:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3;border:none}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height)/1.2);min-height:calc(var(--app-standard-height)/1.2);max-height:calc(var(--app-standard-height)/1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height)/2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height)/2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height)/2);min-height:calc(var(--app-standard-height)/2);max-height:calc(var(--app-standard-height)/2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height)/3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height)/3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover,.gg-select:hover,.gg-input:hover,.gg-textarea:hover,.gg-icon-button:hover{background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height)/2);height:calc(var(--app-standard-height)/2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}
25
32
  </style><style>
26
- input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var(--bkg-color-input);padding-right:0}input:focus{border:1px solid var(--lt-color-gray-900)}button{border:solid 1px var(--bkg-color);color:var(--text-color);background-color:var(--bkg-color);cursor:pointer;padding:0}button:hover{border:solid 1px var(--text-color-grad2)}button.selected{border:solid 1px var(--text-color-grad2);background-color:var(--bkg-color-grad1);color:var(--bkg-color)}#toolbar{flex-wrap:wrap;display:flex}.label-container{flex-grow:1}.text-end{text-align:end}.icon{width:1.2rem;height:1.2rem;fill:var(--text-color);flex-shrink:0;margin:3px}.icon:hover{fill:var(--text-color-grad2)}.gg-icon-button:hover{border:none}.colorPicker{border:1px solid var(--text-color);border-radius:5px}.picker_wrapper{transform:translate(-250px)}.picker_arrow{transform:translate(200px)rotate(90deg)scaleX(-1)!important}.picker_wrapper,.picker_arrow:after,.picker_arrow:before{background-color:var(--bkg-color)!important}.picker_wrapper,.picker_arrow:before{box-shadow:0 0 10px 1px var(--text-color-grad1)!important}button:disabled,input:disabled,.disabled{pointer-events:none;opacity:.5}fieldset.field-wrapper{border:0;margin:0;padding:0}#panel{height:100%;color:var(--text-color);flex-direction:column;display:flex}#panel>div{padding:1rem}.toolParameters{grid-template-columns:auto auto 60px auto;justify-content:left;align-items:center;margin-top:10px;display:grid}.toolParameters>label{padding:0 5px}#drawingListContainer{flex-grow:1;overflow:hidden auto}#drawingList{flex-flow:column;gap:.15rem;display:flex}#drawingList .girafe{border:solid 1px var(--text-color);flex-wrap:wrap;align-items:center;padding:.3rem;display:flex;position:relative}#drawingList .girafe span{flex-grow:1;padding-left:5px}#options{box-shadow:0px -2px 3px -1px var(--text-color-grad1);z-index:100;flex-direction:column;display:flex;position:relative}#optionsTitle{text-align:center;margin-bottom:20px;font-size:1.2rem}#options hr{width:100%;margin:8px 0}#optionsTextLines,#optionsColorLine,#optionsLineLines{align-items:center;display:grid}#optionsText{margin:auto}#optionsTextLines{grid-template-columns:2fr 2fr 1fr 4em 1fr 1fr}#optionsTextLines button:hover{border:none}#optionsColor,#optionsLine,#optionsExport,#optionsArrow{margin:auto}#optionsColorLine{display:flex}#optionsColorLine>div{align-items:center;width:100%;display:flex}#optionsLineLines,#optionsArrowStyle{grid-template-columns:3fr 4em 1fr auto}#optionsExportLine{grid-template-columns:60px 60px 45px 45px;gap:.2rem;display:flex}
33
+ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var(--bkg-color-input);padding-right:0}input:focus{border:1px solid var(--lt-color-gray-900)}button{border:solid 1px var(--bkg-color);color:var(--text-color);background-color:var(--bkg-color);cursor:pointer;padding:0}button:hover{border:solid 1px var(--text-color-grad2)}button.selected{border:solid 1px var(--text-color-grad2);background-color:var(--bkg-color-grad1);color:var(--bkg-color)}#toolbar{flex-wrap:wrap;display:flex}.label-container{flex-grow:1}.text-end{text-align:end}.icon{width:1.2rem;height:1.2rem;fill:var(--text-color);flex-shrink:0;margin:3px}.icon:hover{fill:var(--text-color-grad2)}.gg-icon-button:hover{border:none}.colorPicker{border:1px solid var(--text-color);border-radius:5px}.picker_wrapper{transform:translate(-250px)}.picker_arrow{transform:translate(200px)rotate(90deg)scaleX(-1)!important}.picker_wrapper,.picker_arrow:after,.picker_arrow:before{background-color:var(--bkg-color)!important}.picker_wrapper,.picker_arrow:before{box-shadow:0 0 10px 1px var(--text-color-grad1)!important}button:disabled,input:disabled,.disabled{pointer-events:none;opacity:.5}fieldset.field-wrapper{border:0;margin:0;padding:0}#panel{height:100%;color:var(--text-color);flex-direction:column;display:flex}#panel>div{padding:1rem}#toolParametersContainer{& .title{margin-top:.5rem;margin-bottom:.75rem;display:inline-block}}.toolParameters{flex-direction:column;justify-content:left;row-gap:.25rem;display:flex}.toolParameters>label{padding:0 5px}#drawingListContainer{flex-grow:1;overflow:hidden auto;padding-top:0!important;& .titleContainer{margin-bottom:1rem;display:flex;& .title{flex-grow:1;align-items:center;display:flex}}}#drawingList{flex-flow:column;gap:.15rem;display:flex}#drawingList .girafe{border:solid 1px var(--text-color);flex-wrap:wrap;align-items:center;padding:.3rem;display:flex;position:relative}#drawingList .girafe span{flex-grow:1;padding-left:5px}#options{box-shadow:0px -2px 3px -1px var(--text-color-grad1);z-index:100;flex-direction:column;display:flex;position:relative}#optionsTitle{text-align:center;margin-bottom:20px;font-size:1.2rem}#options hr{width:100%;margin:8px 0}#optionsTextLines,#optionsColorLine,#optionsLineLines{align-items:center;display:grid}#optionsText{margin:auto}#optionsTextLines{grid-template-columns:2fr 2fr 1fr 4em 1fr 1fr}#optionsTextLines button:hover{border:none}#optionsColor,#optionsLine,#optionsExport,#optionsArrow{margin:auto}#optionsColorLine{display:flex}#optionsColorLine>div{align-items:center;width:100%;display:flex}#optionsLineLines,#optionsArrowStyle{grid-template-columns:3fr 4em 1fr auto}#optionsExportLine{grid-template-columns:60px 60px 45px 45px;gap:.2rem;display:flex}
27
34
  </style>
28
- <link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="panel"><div><div id="toolbar"><button id="disable" tip="Disable drawing" class="gg-icon-button gg-medium"><img alt="select icon" src="icons/arrow.svg"></button> <button id="point" tip="Point" class="gg-icon-button gg-medium"><img alt="point icon" src="icons/point.svg"></button> <button id="line" tip="Line" class="gg-icon-button gg-medium"><img alt="polyline icon" src="icons/polyline.svg"></button> <button id="polygon" tip="Polygon" class="gg-icon-button gg-medium"><img alt="polygon icon" src="icons/polygon.svg"></button> <button id="square" tip="Square" class="gg-icon-button gg-medium"><img alt="square icon" src="icons/square.svg"></button> <button id="rectangle" tip="Rectangle" class="gg-icon-button gg-medium"><img alt="rectangle icon" src="icons/rectangle.svg"></button> <button id="circle" tip="Circle" class="gg-icon-button gg-medium"><img alt="circle icon" src="icons/circle.svg"></button> <button id="freeline" tip="Freehand line" class="gg-icon-button gg-medium"><img alt="polyline-free icon" src="icons/polyline-free.svg"></button> <button id="freepolygon" tip="Freehand polygon" class="gg-icon-button gg-medium"><img alt="polygon-free icon" src="icons/polygon-free.svg"></button></div><div class="toolParameters"><button id="fixedLengthEnabled" class="gg-icon-button icon" disabled="${!this.fixedLengthOptionAllowed()}" onclick="${() => this.onToggleFixedLength()}">${this.htmlUnsafe(this.fixedLengthEnabled ? this.checkedIcon : this.noCheckedIcon)}</button> <label class="${this.fixedLengthEnabled && this.fixedLengthOptionAllowed() ? 'gg-label' : 'gg-label disabled'}" for="fixedLengthValue" i18n="Fix length to">Fix length to</label> <input class="gg-input" disabled="${!(this.fixedLengthEnabled && this.fixedLengthOptionAllowed())}" type="number" id="fixedLengthValue"> <label class="${this.fixedLengthEnabled && this.fixedLengthOptionAllowed() ? 'gg-label' : 'gg-label disabled'}" disabled="${!(this.fixedLengthEnabled && this.fixedLengthOptionAllowed())}" for="fixedLengthValue" i18n="meters">meters</label></div></div><div id="drawingListContainer"><div id="drawingList">${this.drawingState.features.map(feature => uHtmlFor(feature, feature.id) `<div id="${'f-' + feature.id}" class="girafe"><button id="${'f-select-' + feature.id}" class="gg-icon-button gg-small" tip="Select to change appearance" onclick="${() => this.onToggleFeatureSelection(feature)}"><div class="icon">${this.htmlUnsafe(feature.selected ? this.checkedIcon : this.noCheckedIcon)}</div></button><div class="label-container"><button class="${feature.selected ? 'selectable-label gg-icon-button gg-small gg-selected' : 'selectable-label gg-icon-button gg-small gg-opacity'}" onclick="${() => this.onToggleFeatureSelection(feature)}"><span id="${'f-name-' + feature.id}">${feature.name}</span></button></div><button class="gg-icon-button icon" tip="Center on shape" onclick="${() => this.olDrawing.centerViewOnFeature(feature)}">${this.htmlUnsafe(this.locateIcon)}</button> <button class="gg-icon-button icon" tip="Delete shape" onclick="${() => this.deleteFeature(feature)}">${this.htmlUnsafe(this.trashIcon)}</button></div>`)}</div></div><div id="options" class="${this.selectedFeatures.length > 0 ? '' : 'disabled'}"><fieldset class="field-wrapper" disabled="${this.selectedFeatures.length <= 0}"><input id="optionsTitle" value="${this.getOptionsTitle()}" class="gg-input" disabled="${this.selectedFeatures.length > 1}"><div id="optionsText"><div id="optionsTextLines"><span i18n="Name">Name</span> <button class="gg-icon-button icon" id="visibleIconName" tip="Show or hide shape name" onclick="${() => this.toggleNameVisibility()}">${this.htmlUnsafe(this.isDisplayNameEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsNameFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.nameFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="nameColorPicker"></button> <span i18n="Measures">Measures</span> <button class="gg-icon-button icon" id="visibleIconMeasure" tip="Show or hide measure information" onclick="${() => this.toggleMeasureVisibility()}">${this.htmlUnsafe(this.isDisplayMeasureEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsMeasuresFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.measureFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="measureColorPicker"></button></div></div><hr><div id="optionsColor"><div id="optionsColorLine"><div><span class="text-end" i18n="Stroke color">Stroke color</span> <button class="icon colorPicker" id="strokePicker"></button></div><div><span class="${this.isFillColorEnabled() ? 'text-end' : 'text-end disabled'}" id="fillPickerSpan" i18n="Fill color">Fill color</span> <button class="icon colorPicker" disabled="${!this.isFillColorEnabled()}" id="fillPicker"></button></div></div></div><hr><div id="optionsLine"><div id="optionsLineLines"><span i18n="Line width">Line width</span> <input id="optionsStrokeWidth" type="number" class="gg-input" min="1" value="${this.selectedFeatures[0]?.strokeWidth}" oninput="${() => this.onOptionsChange()}"> <span>px</span> <select id="line-style" class="gg-select" onchange="${() => this.onOptionsChange()}">${Object.entries(this.lineStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.lineStroke === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsArrow"><div class="${this.isLineStyleEnabled() ? '' : 'disabled'}" id="optionsArrowStyles"><span i18n="Arrows style">Arrows style</span> <select id="arrow-style" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowStyle === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select> <select id="arrow-position" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowPositions).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowPosition === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsExport"><div id="optionsExportLine"><label for="export" class="gg-label" i18n="Export">Export</label> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('geojson')}">GeoJson</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('kml')}">KML</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('gpx')}">GPX</button></div></div></fieldset></div></div>`;
35
+ <link rel="stylesheet" href="lib/vanilla-picker/vanilla-picker.csp.css"><link rel="stylesheet" href="styles/girafecolorpicker.css"><div id="panel"><div><div id="toolbar"><button id="disable" tip="Disable drawing" class="gg-icon-button gg-medium"><img alt="select icon" src="icons/arrow.svg"></button> <button id="point" tip="Point" class="gg-icon-button gg-medium"><img alt="point icon" src="icons/point.svg"></button> <button id="line" tip="Line" class="gg-icon-button gg-medium"><img alt="polyline icon" src="icons/polyline.svg"></button> <button id="polygon" tip="Polygon" class="gg-icon-button gg-medium"><img alt="polygon icon" src="icons/polygon.svg"></button> <button id="square" tip="Square" class="gg-icon-button gg-medium"><img alt="square icon" src="icons/square.svg"></button> <button id="rectangle" tip="Rectangle" class="gg-icon-button gg-medium"><img alt="rectangle icon" src="icons/rectangle.svg"></button> <button id="circle" tip="Circle" class="gg-icon-button gg-medium"><img alt="circle icon" src="icons/circle.svg"></button> <button id="freeline" tip="Freehand line" class="gg-icon-button gg-medium"><img alt="polyline-free icon" src="icons/polyline-free.svg"></button> <button id="freepolygon" tip="Freehand polygon" class="gg-icon-button gg-medium"><img alt="polygon-free icon" src="icons/polygon-free.svg"></button></div><div id="toolParametersContainer"><span i18n="Settings" class="title"></span><div class="toolParameters" data-tool="Polyline,Polygon"><girafe-fixed-dimension dimensionname="length" dimension="length" id="fixedLineLength" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension></div><div class="toolParameters" data-tool="Square"><girafe-fixed-dimension dimensionname="side length" dimension="side" id="fixedSquareSide" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension></div><div class="toolParameters" data-tool="Rectangle"><girafe-fixed-dimension dimensionname="width" dimension="width" id="fixedRectangleWidth" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension><girafe-fixed-dimension dimensionname="height" dimension="height" id="fixedRectangleHeight" @fixed-dimension:value-changed="${(e) => this.fixedDimensionValueChangedHandler(e)}"></girafe-fixed-dimension></div></div></div><div id="drawingListContainer"><div class="titleContainer"><span i18n="Drawing List" class="title"></span> <button class="gg-icon-button icon" tip="Delete all shapes" onclick="${() => this.deleteAllFeatures()}" ?disabled="${this.drawingState.features.length === 0}">${this.htmlUnsafe(this.trashIcon)}</button></div><div id="drawingList">${this.drawingState.features.map(feature => uHtmlFor(feature, feature.id) `<div id="${'f-' + feature.id}" class="girafe"><button id="${'f-select-' + feature.id}" class="gg-icon-button gg-small" tip="Select to change appearance" onclick="${() => this.onToggleFeatureSelection(feature)}"><div class="icon">${this.htmlUnsafe(feature.selected ? this.checkedIcon : this.noCheckedIcon)}</div></button><div class="label-container"><button class="${feature.selected ? 'selectable-label gg-icon-button gg-small gg-selected' : 'selectable-label gg-icon-button gg-small gg-opacity'}" onclick="${() => this.onToggleFeatureSelection(feature)}"><span id="${'f-name-' + feature.id}">${feature.name}</span></button></div><button class="gg-icon-button icon" tip="Center on shape" onclick="${() => this.olDrawing.centerViewOnFeature(feature)}">${this.htmlUnsafe(this.locateIcon)}</button> <button class="gg-icon-button icon" tip="Delete shape" onclick="${() => this.deleteFeature(feature)}">${this.htmlUnsafe(this.trashIcon)}</button></div>`)}</div></div><div id="options" class="${this.selectedFeatures.length > 0 ? '' : 'disabled'}"><fieldset class="field-wrapper" disabled="${this.selectedFeatures.length <= 0}"><input id="optionsTitle" value="${this.getOptionsTitle()}" class="gg-input" disabled="${this.selectedFeatures.length > 1}"><div id="optionsText"><div id="optionsTextLines"><span i18n="Name">Name</span> <button class="gg-icon-button icon" id="visibleIconName" tip="Show or hide shape name" onclick="${() => this.toggleNameVisibility()}">${this.htmlUnsafe(this.isDisplayNameEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsNameFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.nameFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="nameColorPicker"></button> <span i18n="Measures">Measures</span> <button class="gg-icon-button icon" id="visibleIconMeasure" tip="Show or hide measure information" onclick="${() => this.toggleMeasureVisibility()}">${this.htmlUnsafe(this.isDisplayMeasureEnabled() ? this.visibleIcon : this.notVisibleIcon)}</button> <span i18n="Font">Font</span> <input id="optionsMeasuresFontSize" class="gg-input" type="number" min="1" value="${this.selectedFeatures[0]?.measureFontSize}" oninput="${() => this.onOptionsChange()}"> <span>pt</span> <button class="icon colorPicker" id="measureColorPicker"></button></div></div><hr><div id="optionsColor"><div id="optionsColorLine"><div><span class="text-end" i18n="Stroke color">Stroke color</span> <button class="icon colorPicker" id="strokePicker"></button></div><div><span class="${this.isFillColorEnabled() ? 'text-end' : 'text-end disabled'}" id="fillPickerSpan" i18n="Fill color">Fill color</span> <button class="icon colorPicker" disabled="${!this.isFillColorEnabled()}" id="fillPicker"></button></div></div></div><hr><div id="optionsLine"><div id="optionsLineLines"><span i18n="Line width">Line width</span> <input id="optionsStrokeWidth" type="number" class="gg-input" min="1" value="${this.selectedFeatures[0]?.strokeWidth}" oninput="${() => this.onOptionsChange()}"> <span>px</span> <select id="line-style" class="gg-select" onchange="${() => this.onOptionsChange()}">${Object.entries(this.lineStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.lineStroke === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsArrow"><div class="${this.isLineStyleEnabled() ? '' : 'disabled'}" id="optionsArrowStyles"><span i18n="Arrows style">Arrows style</span> <select id="arrow-style" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowStyles).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowStyle === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select> <select id="arrow-position" class="gg-select" onchange="${() => this.onArrowsChange()}">${Object.entries(this.arrowPositions).map((entry) => uHtml `<option selected="${this.selectedFeatures[0]?.arrowPosition === entry[0]}" value="${entry[0]}"><span>${entry[1]}</span></option>`)}</select></div></div><hr><div id="optionsExport"><div id="optionsExportLine"><label for="export" class="gg-label" i18n="Export">Export</label> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('geojson')}">GeoJson</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('kml')}">KML</button> <button class="gg-button" onclick="${() => this.exportSelectedFeatures('gpx')}">GPX</button></div></div></fieldset></div></div>`;
29
36
  };
30
37
  isPanelVisible = false;
31
38
  panelTitle = 'drawing-panel';
@@ -111,24 +118,6 @@ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var
111
118
  this.selectedFeatures[0].name = e.target.value;
112
119
  this.refreshRender();
113
120
  };
114
- this.getById('fixedLengthValue').oninput = (e) => {
115
- const val = parseFloat(e.target.value);
116
- this.olDrawing.setFixedLength(val);
117
- this.cesiumDrawing.setFixedLength(val);
118
- };
119
- this.getById('fixedLengthEnabled').onchange = (e) => {
120
- const elements = Array.from(this.shadowRoot.querySelectorAll('.fixedLengthElement'));
121
- const option = e.target;
122
- if (!option.disabled && option.checked) {
123
- elements.forEach((e) => e.classList.remove('disabled'));
124
- this.getById('fixedLengthValue').dispatchEvent(new Event('input'));
125
- }
126
- else {
127
- elements.forEach((e) => e.classList.add('disabled'));
128
- this.olDrawing.setFixedLength(0);
129
- this.cesiumDrawing.setFixedLength(0);
130
- }
131
- };
132
121
  this.setTool();
133
122
  }
134
123
  this.warnWhenInWebMercator();
@@ -172,16 +161,39 @@ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var
172
161
  this.toolSelected = this.getById(this.buttons.find((x) => x.tool == tool).id);
173
162
  this.toolSelected.classList.add('selected');
174
163
  this.drawingState.activeTool = tool;
175
- }
176
- fixedLengthOptionAllowed() {
177
- // Enable / disable fix length checkbox based on current tool
178
- return ![
179
- null,
180
- DrawingShape.Point,
181
- DrawingShape.Rectangle,
182
- DrawingShape.FreehandPolyline,
183
- DrawingShape.FreehandPolygon
184
- ].includes(this.drawingState.activeTool);
164
+ this.showToolParameters(tool);
165
+ }
166
+ showToolParameters(tool = null) {
167
+ const toolName = tool ? DrawingShape[tool] : 'Pointer';
168
+ const toolParametersList = this.shadowRoot.querySelectorAll('.toolParameters');
169
+ let hasParameters = false;
170
+ toolParametersList.forEach((toolParameters) => {
171
+ const isParametersForTool = toolParameters.dataset.tool?.includes(toolName) ?? false;
172
+ toolParameters.style.display = isParametersForTool ? 'flex' : 'none';
173
+ hasParameters ||= isParametersForTool;
174
+ });
175
+ this.shadow.querySelector('#toolParametersContainer span.title').style.display = hasParameters
176
+ ? 'inline-block'
177
+ : 'none';
178
+ }
179
+ fixedDimensionValueChangedHandler(e) {
180
+ const details = e.detail;
181
+ switch (details.id) {
182
+ case 'fixedLineLength':
183
+ this.olDrawing.setFixedLineLength(details.value);
184
+ break;
185
+ case 'fixedSquareSide':
186
+ this.olDrawing.setFixedSquareSide(details.value);
187
+ break;
188
+ case 'fixedRectangleWidth':
189
+ this.olDrawing.setFixedRectangleWidth(details.value);
190
+ break;
191
+ case 'fixedRectangleHeight':
192
+ this.olDrawing.setFixedRectangleHeight(details.value);
193
+ break;
194
+ default:
195
+ console.debug('Value changed for unknown Dimension with id', details.id);
196
+ }
185
197
  }
186
198
  connectedCallback() {
187
199
  super.connectedCallback();
@@ -287,20 +299,12 @@ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var
287
299
  }
288
300
  }
289
301
  onToggleBatchMode() {
290
- // Currently not used, will possibly be part of advanced editing/drawing tools
291
302
  this.batchCreateMode = !this.batchCreateMode;
292
303
  if (this.batchCreateMode) {
293
304
  this.deselectAllFeatures();
294
305
  }
295
306
  this.refreshRender();
296
307
  }
297
- onToggleFixedLength() {
298
- this.fixedLengthEnabled = !this.fixedLengthEnabled;
299
- const val = this.fixedLengthEnabled ? parseFloat(this.getById('fixedLengthValue').value) : 0;
300
- this.olDrawing.setFixedLength(val);
301
- this.cesiumDrawing.setFixedLength(val);
302
- this.refreshRender();
303
- }
304
308
  onToggleFeatureSelection(feature) {
305
309
  this.setTool(null);
306
310
  feature.selected = !feature.selected;
@@ -349,6 +353,13 @@ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var
349
353
  }
350
354
  }
351
355
  }
356
+ async deleteAllFeatures() {
357
+ const confirm = await window.gConfirm('Do you want to remove all features?', 'Delete Features');
358
+ if (confirm) {
359
+ this.drawingState.features = [];
360
+ this.refreshRender();
361
+ }
362
+ }
352
363
  onOptionsChange() {
353
364
  const nameFontSize = parseInt(this.getById('optionsNameFontSize').value);
354
365
  const measureFontSize = parseInt(this.getById('optionsMeasuresFontSize').value);
@@ -413,3 +424,24 @@ input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var
413
424
  }
414
425
  }
415
426
  }
427
+ __decorate([
428
+ UsedInTemplateOnly()
429
+ ], DrawingComponent.prototype, "fixedDimensionValueChangedHandler", null);
430
+ __decorate([
431
+ UsedInTemplateOnly('Currently not used, will possibly be part of advanced editing/drawing tools')
432
+ ], DrawingComponent.prototype, "onToggleBatchMode", null);
433
+ __decorate([
434
+ UsedInTemplateOnly()
435
+ ], DrawingComponent.prototype, "getOptionsTitle", null);
436
+ __decorate([
437
+ UsedInTemplateOnly()
438
+ ], DrawingComponent.prototype, "isDisplayNameEnabled", null);
439
+ __decorate([
440
+ UsedInTemplateOnly()
441
+ ], DrawingComponent.prototype, "isDisplayMeasureEnabled", null);
442
+ __decorate([
443
+ UsedInTemplateOnly()
444
+ ], DrawingComponent.prototype, "isLineStyleEnabled", null);
445
+ __decorate([
446
+ UsedInTemplateOnly()
447
+ ], DrawingComponent.prototype, "isFillColorEnabled", null);
@@ -0,0 +1,39 @@
1
+ import GirafeHTMLElement from '../../../base/GirafeHTMLElement.js';
2
+ export type FixedDimensionValueChangedEventDetails = {
3
+ id: string;
4
+ dimension: string;
5
+ value: number;
6
+ };
7
+ export type DimensionUnit = {
8
+ name: string;
9
+ factor: number;
10
+ };
11
+ declare class FixedDimensionComponent extends GirafeHTMLElement {
12
+ static readonly observedAttributes: string[];
13
+ template: () => import("uhtml").Hole;
14
+ checkedIcon: string;
15
+ notCheckedIcon: string;
16
+ dimensionName: string;
17
+ dimension: string;
18
+ dimensionUnits: string;
19
+ onChange: string;
20
+ fixedDimensionEnabled: boolean;
21
+ renderedOnce: boolean;
22
+ lastValue: string;
23
+ units: DimensionUnit[];
24
+ unit: DimensionUnit | undefined;
25
+ constructor(name?: string);
26
+ render(): void;
27
+ private renderComponent;
28
+ protected connectedCallback(): void;
29
+ private refreshDimensionName;
30
+ private refreshDimension;
31
+ private refreshDimensionUnits;
32
+ private refreshOnChange;
33
+ toggleFixedDimensionEnabled(): void;
34
+ fixedValueChanged(e: InputEvent): void;
35
+ dimensionUnitChanged(e: Event): void;
36
+ dispatchFixedDimensionValueChangedEvent(valueAsString: string): void;
37
+ protected attributeChangedCallback(name: string, _oldValue: string, newValue: string): void;
38
+ }
39
+ export default FixedDimensionComponent;
@@ -0,0 +1,123 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html as uHtml } from 'uhtml';
8
+ import GirafeHTMLElement from '../../../base/GirafeHTMLElement.js';
9
+ import checkedIcon from '../../../assets/icons/checked-full.svg?raw';
10
+ import checkedNoIcon from '../../../assets/icons/checked-no.svg?raw';
11
+ import { UsedInTemplateOnly } from '../../../decorators.js';
12
+ const defaultUnits = 'm:1;km:1000';
13
+ class FixedDimensionComponent extends GirafeHTMLElement {
14
+ static observedAttributes = ['dimensionName', 'dimension', 'dimensionUnits', 'onChange'];
15
+ template = () => {
16
+ return uHtml `<style>
17
+ *{font-family:Arial,sans-serif}.hidden{display:none!important}.gg-rotate90{transform:rotate(90deg)}.gg-rotate180{transform:rotate(180deg)}.gg-rotate270{transform:rotate(270deg)}img{filter:var(--svg-filter)}img.legend-image{filter:var(--svg-map-filter);background:var(--svg-legend-bkg)}div{scrollbar-width:thin}a,a:visited{color:var(--link-color)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes spin-wait{0%{transform:rotate(0)}7%{transform:rotate(360deg)}to{transform:rotate(360deg)}}.gg-spin{animation-name:spin;animation-duration:2s;animation-timing-function:linear;animation-iteration-count:infinite}.gg-spin-wait{animation-name:spin-wait;animation-duration:10s;animation-timing-function:linear;animation-iteration-count:infinite}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-thumb{background:#999}.gg-button,.gg-select,.gg-input,.gg-textarea{background-color:var(--bkg-color);color:var(--text-color);border:var(--app-standard-border);box-sizing:border-box;cursor:pointer;border-radius:3px;outline:0;margin:0;padding:0 0 0 .5rem;display:inline-block}.gg-label{background-color:var(--bkg-color);color:var(--text-color);border:none;align-items:center;margin:0;padding:0;display:flex}.gg-button,.gg-select,.gg-input,.gg-label{min-height:calc(var(--app-standard-height)/1.5)}.gg-textarea{max-height:initial;resize:vertical;height:6rem;padding:.5rem;line-height:1.3rem}.gg-input{cursor:text}.gg-checkbox{accent-color:var(--text-color);width:1.2rem}.gg-range{accent-color:var(--text-color)}.gg-button{padding:0 .5rem}.gg-button.active{border:solid 1px var(--text-color-grad2);background-color:var(--text-color-grad2);color:var(--bkg-color)}.gg-button:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3;border:none}.gg-input:disabled,.gg-select:disabled,.gg-textarea:disabled{color:gray;cursor:not-allowed;background-color:#d3d3d3}.gg-button>img{vertical-align:middle}.gg-icon-button{color:var(--text-color);cursor:pointer;background-color:#0000;border:none;flex-direction:column;justify-content:center;align-items:center;padding:0;display:flex}.gg-icon{justify-content:center;align-items:center;display:flex}.gg-big,.gg-big-withtext{min-width:var(--app-standard-height);min-height:var(--app-standard-height);max-height:var(--app-standard-height)}.gg-big img,.gg-big-withtext img{width:calc(var(--app-standard-height) - 1.5rem);margin:0}.gg-big-withtext span{font-variant:small-caps;padding:0 1rem;font-size:.9rem}.gg-medium,.gg-medium-withtext{min-width:calc(var(--app-standard-height)/1.2);min-height:calc(var(--app-standard-height)/1.2);max-height:calc(var(--app-standard-height)/1.2);flex-direction:row}.gg-medium img{width:calc(var(--app-standard-height)/2.4);margin:0}.gg-medium-withtext img{width:calc(var(--app-standard-height)/2.4);margin-left:.5rem}.gg-medium-withtext span{padding:0 1rem 0 .5rem;font-size:.9rem}.gg-small,.gg-small-withtext{min-width:calc(var(--app-standard-height)/2);min-height:calc(var(--app-standard-height)/2);max-height:calc(var(--app-standard-height)/2);flex-direction:row}.gg-small img{width:calc(var(--app-standard-height)/3);margin:0}.gg-small-withtext img{width:calc(var(--app-standard-height)/3);margin-left:.5rem}.gg-small-withtext span{padding:0 .5rem 0 .3rem;font-size:.9rem}.gg-button:hover,.gg-select:hover,.gg-input:hover,.gg-textarea:hover,.gg-icon-button:hover{background-color:var(--bkg-color-grad1)}.gg-opacity{opacity:.5}.gg-opacity:hover{opacity:1;background-color:#0000}.gg-tabs{cursor:pointer;grid-auto-flow:column;padding-bottom:1rem;font-size:1rem;display:grid}.gg-tab{border:none;border-bottom:var(--app-standard-border);cursor:pointer;color:var(--text-color);background:0 0;padding:.5rem}.gg-tab.active{border-bottom:solid 1px var(--text-color)}.girafe-button-big,.girafe-button-large,.girafe-button-small,.girafe-button-tiny{color:var(--text-color);background-color:#0000;border:none;flex-direction:column;display:flex}.girafe-button-big:hover,.girafe-button-large:hover,.girafe-button-small:hover,.girafe-button-tiny:hover{background-color:var(--bkg-color-grad1);cursor:pointer}.girafe-button-big.dark,.girafe-button-large.dark,.girafe-button-small.dark,.girafe-button-tiny.dark{background-color:var(--bkg-color);filter:invert()}.girafe-button-big{width:var(--app-standard-height);height:var(--app-standard-height);align-items:center;padding:1rem}.girafe-button-big img{overflow:hidden}.girafe-button-large{flex-direction:row}.girafe-button-large img{height:2rem;margin:.3rem}.girafe-button-large span{height:2rem;margin:.3rem;line-height:2rem}.girafe-button-small{min-width:calc(var(--app-standard-height)/2);height:calc(var(--app-standard-height)/2);align-items:center;padding:.5rem}.girafe-button-small img{overflow:hidden}.girafe-button-small span{text-align:left;text-overflow:ellipsis;width:100%;overflow:hidden}.girafe-button-tiny{align-items:center;width:1rem;height:1rem;padding:0}.girafe-button-tiny img{overflow:hidden}.girafe-onboarding-theme{background-color:var(--bkg-color)!important;color:var(--text-color)!important}.girafe-onboarding-theme button{background-color:var(--bkg-color)!important;color:var(--text-color)!important;text-shadow:none!important}.girafe-onboarding-theme button.driver-popover-close-btn{z-index:10000}
18
+ </style><style>
19
+ :host{grid-template-columns:auto auto 60px auto;justify-content:left;align-items:center;display:grid}input{border:1px solid var(--bkg-color-grad1);width:inherit;background-color:var(--bkg-color-input);padding-right:0}input:focus{border:1px solid var(--lt-color-gray-900)}button{border:solid 1px var(--bkg-color);color:var(--text-color);background-color:var(--bkg-color);cursor:pointer;padding:0}button:hover{border:solid 1px var(--text-color-grad2)}button.selected{border:solid 1px var(--text-color-grad2);background-color:var(--bkg-color-grad1);color:var(--bkg-color)}.icon{width:1.2rem;height:1.2rem;fill:var(--text-color);flex-shrink:0;margin:3px}.icon:hover{fill:var(--text-color-grad2)}.gg-icon-button:hover{border:none}button:disabled,input:disabled,.disabled{pointer-events:none;opacity:.5}label.gg-label{padding:0 5px!important;&.disabled{pointer-events:revert}}
20
+ </style>
21
+ <button class="gg-icon-button icon" onclick="${() => this.toggleFixedDimensionEnabled()}">${this.htmlUnsafe(this.fixedDimensionEnabled ? this.checkedIcon : this.notCheckedIcon)}</button> <label class="${this.fixedDimensionEnabled ? 'gg-label' : 'gg-label disabled'}" onclick="${() => this.toggleFixedDimensionEnabled()}" onkeyup="${() => this.toggleFixedDimensionEnabled()}" for="fixedValue" i18n="${'Fix ' + this.dimensionName + ' to'}"></label> <input class="gg-input" disabled="${!this.fixedDimensionEnabled}" oninput="${(e) => this.fixedValueChanged(e)}" type="number" id="fixedValue"> <select id="dimensionUnits" class="gg-select" disabled="${!this.fixedDimensionEnabled}" onchange="${(e) => this.dimensionUnitChanged(e)}">${this.units.map((unit) => uHtml `<option ?selected="${this.unit?.name === unit.name}" value="${unit.factor}">${unit.name}</option>`)}</select>`;
22
+ };
23
+ checkedIcon = checkedIcon;
24
+ notCheckedIcon = checkedNoIcon;
25
+ dimensionName = 'dimension';
26
+ dimension = 'dimension';
27
+ dimensionUnits = defaultUnits;
28
+ onChange = '';
29
+ fixedDimensionEnabled = false;
30
+ renderedOnce = false;
31
+ lastValue = '0';
32
+ units = [];
33
+ unit = undefined;
34
+ constructor(name = 'fixed-dimension') {
35
+ super(name);
36
+ this.displayStyle = 'grid';
37
+ }
38
+ render() {
39
+ super.render();
40
+ this.refreshDimensionName();
41
+ this.refreshDimension();
42
+ this.refreshDimensionUnits();
43
+ this.refreshOnChange();
44
+ this.renderComponent();
45
+ super.girafeTranslate();
46
+ }
47
+ renderComponent() {
48
+ this.show();
49
+ if (!this.renderedOnce) {
50
+ this.renderedOnce = true;
51
+ }
52
+ }
53
+ connectedCallback() {
54
+ super.connectedCallback();
55
+ this.render();
56
+ }
57
+ refreshDimensionName() {
58
+ this.dimensionName = this.getAttribute('dimensionName') ?? 'dimension';
59
+ this.refreshRender();
60
+ }
61
+ refreshDimension() {
62
+ this.dimension = this.getAttribute('dimension') ?? 'dimension';
63
+ }
64
+ refreshDimensionUnits(dimensionUnits = defaultUnits) {
65
+ console.log(`Refreshing dimension units for ${this.dimension} with units ${dimensionUnits}`);
66
+ this.dimensionUnits = dimensionUnits ?? this.getAttribute('dimensionUnits') ?? defaultUnits;
67
+ this.units = this.dimensionUnits.split(';').map((unit) => {
68
+ const [name, factor] = unit.split(':');
69
+ return { name, factor: Number.parseFloat(factor) };
70
+ });
71
+ this.unit = this.units[0];
72
+ this.refreshRender();
73
+ }
74
+ refreshOnChange() {
75
+ this.onChange = this.getAttribute('onChange') ?? '';
76
+ console.log(`Refreshing onChange for ${this.dimension} with onChange ${this.onChange}`);
77
+ }
78
+ toggleFixedDimensionEnabled() {
79
+ this.fixedDimensionEnabled = !this.fixedDimensionEnabled;
80
+ this.dispatchFixedDimensionValueChangedEvent(this.fixedDimensionEnabled ? this.lastValue : '0');
81
+ this.refreshRender();
82
+ }
83
+ fixedValueChanged(e) {
84
+ this.lastValue = e.target.value;
85
+ this.dispatchFixedDimensionValueChangedEvent(this.lastValue);
86
+ this.htmlUnsafe(this.onChange);
87
+ }
88
+ dimensionUnitChanged(e) {
89
+ const selectedUnitFactor = Number.parseFloat(e.target.value);
90
+ this.unit = this.units.find((unit) => unit.factor == selectedUnitFactor);
91
+ this.dispatchFixedDimensionValueChangedEvent(this.lastValue);
92
+ }
93
+ dispatchFixedDimensionValueChangedEvent(valueAsString) {
94
+ const value = Number.parseFloat(valueAsString);
95
+ this.dispatchEvent(new CustomEvent('fixed-dimension:value-changed', {
96
+ bubbles: true,
97
+ cancelable: true,
98
+ detail: {
99
+ id: this.id,
100
+ dimension: this.dimension,
101
+ value: value * (this.unit?.factor ?? 1)
102
+ }
103
+ }));
104
+ }
105
+ attributeChangedCallback(name, _oldValue, newValue) {
106
+ if (name === 'dimensionName') {
107
+ this.dimensionName = newValue;
108
+ }
109
+ else if (name === 'dimension') {
110
+ this.dimension = newValue;
111
+ }
112
+ else if (name === 'dimensionUnits') {
113
+ this.refreshDimensionUnits(newValue);
114
+ }
115
+ else if (name === 'onChange') {
116
+ this.onChange = newValue;
117
+ }
118
+ }
119
+ }
120
+ __decorate([
121
+ UsedInTemplateOnly('attributeChangedCallback is not used in this component, but it is required by the HTMLElement interface.')
122
+ ], FixedDimensionComponent.prototype, "attributeChangedCallback", null);
123
+ export default FixedDimensionComponent;
@@ -24,7 +24,10 @@ export default class OlDrawing {
24
24
  snap: Snap | null;
25
25
  editContextMenu: ContextMenu | null;
26
26
  currentShape: DrawingShape | null;
27
- fixedLength: number;
27
+ fixedLineLength: number;
28
+ fixedSquareSide: number;
29
+ fixedRectangleWidth: number;
30
+ fixedRectangleHeight: number;
28
31
  drawingSource: VectorSource;
29
32
  drawingLayer: VectorLayer;
30
33
  lastClosestFeature: Feature | null;
@@ -97,11 +100,15 @@ export default class OlDrawing {
97
100
  private getOlFeatureFromDrawingSource;
98
101
  private isOlFeatureInState;
99
102
  createOlFeature(dFeature: DrawingFeature): Feature<Geometry>;
100
- setFixedLength(length: number): void;
103
+ setFixedLineLength(length: number): void;
104
+ setFixedSquareSide(length: number): void;
105
+ setFixedRectangleWidth(width: number): void;
106
+ setFixedRectangleHeight(height: number): void;
101
107
  createLineStringFixedLength(coordinates: SketchCoordType, geom: SimpleGeometry): SimpleGeometry;
102
108
  createSquareFixedLength(coordinates: SketchCoordType, geom: SimpleGeometry, proj: Projection): SimpleGeometry;
103
109
  createPolygonFixedLength(coordinates: SketchCoordType, geom: SimpleGeometry): SimpleGeometry;
104
110
  createDiskFixedLength(coordinates: SketchCoordType, geom: SimpleGeometry): SimpleGeometry;
111
+ createRectangleFixedSides(coordinates: SketchCoordType, geom: SimpleGeometry, proj: Projection): SimpleGeometry;
105
112
  addDrawInteraction(tool: DrawingShape): void;
106
113
  centerViewOnFeature(drawingFeature: DrawingFeature): void;
107
114
  getStyle(dFeature: DrawingFeature, olFeature: Feature<Geometry>): Style[];
@@ -59,7 +59,10 @@ export default class OlDrawing {
59
59
  snap = null;
60
60
  editContextMenu = null;
61
61
  currentShape = null;
62
- fixedLength = 0;
62
+ fixedLineLength = 0;
63
+ fixedSquareSide = 0;
64
+ fixedRectangleWidth = 0;
65
+ fixedRectangleHeight = 0;
63
66
  drawingSource;
64
67
  drawingLayer;
65
68
  lastClosestFeature = null;
@@ -467,29 +470,40 @@ export default class OlDrawing {
467
470
  olFeature.setStyle((f) => this.getStyle(dFeature, f));
468
471
  return olFeature;
469
472
  }
470
- setFixedLength(length) {
471
- this.fixedLength = Number.isNaN(length) ? 0 : length;
473
+ setFixedLineLength(length) {
474
+ this.fixedLineLength = Number.isNaN(length) ? 0 : length;
475
+ }
476
+ setFixedSquareSide(length) {
477
+ this.fixedSquareSide = Number.isNaN(length) ? 0 : length;
478
+ }
479
+ setFixedRectangleWidth(width) {
480
+ this.fixedRectangleWidth = Number.isNaN(width) ? 0 : width;
481
+ }
482
+ setFixedRectangleHeight(height) {
483
+ this.fixedRectangleHeight = Number.isNaN(height) ? 0 : height;
472
484
  }
473
485
  createLineStringFixedLength(coordinates, geom) {
474
- this.fixLastLength(this.fixedLength, coordinates);
486
+ this.fixLastLength(this.fixedLineLength, coordinates);
475
487
  geom = geom ?? new LineString(coordinates);
476
488
  geom.setCoordinates(coordinates);
477
489
  return geom;
478
490
  }
479
491
  createSquareFixedLength(coordinates, geom, proj) {
480
- this.fixLastLength(this.fixedLength, coordinates, Math.SQRT2);
481
- return createRegularPolygon(4)(coordinates, geom, proj);
492
+ this.fixLastLength(this.fixedSquareSide, coordinates, Math.SQRT2);
493
+ const poly = createRegularPolygon(4)(coordinates, geom, proj);
494
+ console.log('createSquareFixedLength ' + JSON.stringify(poly.getCoordinates()));
495
+ return poly;
482
496
  }
483
497
  createPolygonFixedLength(coordinates, geom) {
484
498
  const coord = coordinates[0];
485
- this.fixLastLength(this.fixedLength, coord);
499
+ this.fixLastLength(this.fixedLineLength, coord);
486
500
  geom = geom ?? new Polygon([coord]);
487
501
  geom.setCoordinates([coord]);
488
502
  return geom;
489
503
  }
490
504
  createDiskFixedLength(coordinates, geom) {
491
505
  const coord = coordinates;
492
- this.fixLastLength(this.fixedLength, coord);
506
+ this.fixLastLength(this.fixedLineLength, coord);
493
507
  geom = geom ?? new CircleGeom(coord[0], getDistance(coord, this.state.projection));
494
508
  geom.setCenterAndRadius(coord[0], getDistance(coord, this.state.projection));
495
509
  geom.setProperties({
@@ -498,6 +512,49 @@ export default class OlDrawing {
498
512
  });
499
513
  return geom;
500
514
  }
515
+ createRectangleFixedSides(coordinates, geom, proj) {
516
+ if (coordinates.length < 2) {
517
+ geom = geom ?? createBox()(coordinates, geom, proj);
518
+ return geom;
519
+ }
520
+ // If no fixed dimensions are set, behave like the normal box drawing.
521
+ if (this.fixedRectangleWidth <= 0 && this.fixedRectangleHeight <= 0) {
522
+ geom = geom ?? createBox()(coordinates, geom, proj);
523
+ return createBox()(coordinates, geom, proj);
524
+ }
525
+ const coords = coordinates;
526
+ const start = coords[0];
527
+ const pointer = coords[1];
528
+ // Decide in which quadrant the user is dragging.
529
+ const signX = pointer[0] >= start[0] ? 1 : -1;
530
+ const signY = pointer[1] >= start[1] ? 1 : -1;
531
+ // Convert "meters" (or whatever your getDistance returns) to map units along X and Y.
532
+ const xUnit = [start[0] + 1, start[1]];
533
+ const yUnit = [start[0], start[1] + 1];
534
+ const metersPerMapUnitX = getDistance([start, xUnit], this.state.projection);
535
+ const metersPerMapUnitY = getDistance([start, yUnit], this.state.projection);
536
+ // Guard against division by 0 in weird edge cases.
537
+ if (metersPerMapUnitX <= 0 || metersPerMapUnitY <= 0) {
538
+ geom = geom ?? createBox()(coordinates, geom, proj);
539
+ return createBox()(coordinates, geom, proj);
540
+ }
541
+ const dxMapUnits = (this.fixedRectangleWidth / metersPerMapUnitX) * signX;
542
+ const dyMapUnits = (this.fixedRectangleHeight / metersPerMapUnitY) * signY;
543
+ if (dxMapUnits != 0 && dyMapUnits != 0) {
544
+ // Overwrite width and height
545
+ coords[1] = [start[0] + dxMapUnits, start[1] + dyMapUnits];
546
+ }
547
+ else if (dxMapUnits != 0) {
548
+ // Overwrite only width
549
+ coords[1] = [start[0] + dxMapUnits, pointer[1]];
550
+ }
551
+ else if (dyMapUnits != 0) {
552
+ // Overwrite only height
553
+ coords[1] = [pointer[0], start[1] + dyMapUnits];
554
+ }
555
+ geom = geom ?? createBox()(coords, geom, proj);
556
+ return createBox()(coords, geom, proj);
557
+ }
501
558
  addDrawInteraction(tool) {
502
559
  this.removeDrawInteraction();
503
560
  // Block feature selection while drawing by registering 'map.select' exclusively
@@ -527,7 +584,7 @@ export default class OlDrawing {
527
584
  break;
528
585
  case DrawingShape.Rectangle:
529
586
  olTool = 'Circle';
530
- geomFunction = createBox();
587
+ geomFunction = this.createRectangleFixedSides.bind(this);
531
588
  break;
532
589
  case DrawingShape.FreehandPolyline:
533
590
  olTool = 'LineString';
@@ -12,6 +12,8 @@ export { default as CrossSectionViewComponent } from './cross-section/cross-sect
12
12
  export { default as DisplayMenuButtonMobile } from './displaymenubutton-mobile/component.js';
13
13
  export { default as DisplaySelectorButtonMobile } from './displayselectorbutton-mobile/component.js';
14
14
  export { default as DrawingComponent } from './drawing/component.js';
15
+ export type { FixedDimensionValueChangedEventDetails, DimensionUnit } from './drawing/fixed-dimension/component.js';
16
+ export { default as FixedDimensionComponent } from './drawing/fixed-dimension/component.js';
15
17
  export { default as DrawingContainerMobile } from './drawing-container-mobile/component.js';
16
18
  export { default as EditComponent } from './edit/component.js';
17
19
  export { default as EditFromComponent } from './edit/editform/component.js';
@@ -12,6 +12,7 @@ export { default as CrossSectionViewComponent } from './cross-section/cross-sect
12
12
  export { default as DisplayMenuButtonMobile } from './displaymenubutton-mobile/component.js';
13
13
  export { default as DisplaySelectorButtonMobile } from './displayselectorbutton-mobile/component.js';
14
14
  export { default as DrawingComponent } from './drawing/component.js';
15
+ export { default as FixedDimensionComponent } from './drawing/fixed-dimension/component.js';
15
16
  export { default as DrawingContainerMobile } from './drawing-container-mobile/component.js';
16
17
  export { default as EditComponent } from './edit/component.js';
17
18
  export { default as EditFromComponent } from './edit/editform/component.js';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Use this Decorator to mark a Method that seems unused but is used in the HTML Template.
3
+ * @constructor
4
+ */
5
+ export declare function UsedInTemplateOnly(_reason?: string): (_target: object, _propertyKey: string, _descriptor: PropertyDescriptor) => void;
package/decorators.js ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Use this Decorator to mark a Method that seems unused but is used in the HTML Template.
3
+ * @constructor
4
+ */
5
+ export function UsedInTemplateOnly(_reason = 'Method is used in HTML Template') {
6
+ return function (_target, _propertyKey, _descriptor) { };
7
+ }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "name": "GeoGirafe PSC",
6
6
  "url": "https://doc.geomapfish.dev"
7
7
  },
8
- "version": "1.1.0-dev.2438155631",
8
+ "version": "1.1.0-dev.2438378072",
9
9
  "type": "module",
10
10
  "engines": {
11
11
  "node": ">=20.19.0"
@@ -1 +1 @@
1
- {"version":"1.1.0-dev.2438155631", "build":"2438155631", "date":"08/04/2026"}
1
+ {"version":"1.1.0-dev.2438378072", "build":"2438378072", "date":"08/04/2026"}
@@ -47,6 +47,7 @@ import { DrawingState } from '../../components/drawing/drawingFeature.js';
47
47
  import DrawingSerializer from '../../components/drawing/drawingSerializer.js';
48
48
  import { ShareState, ShareStateSerializer } from '../../components/share/sharestate.js';
49
49
  import SelectionToolComponent from '../../components/selectiontool/component.js';
50
+ import FixedDimensionComponent from '../../components/drawing/fixed-dimension/component.js';
50
51
  export default class GeoGirafeApp {
51
52
  readyPromise;
52
53
  resolveReady;
@@ -138,6 +139,7 @@ export default class GeoGirafeApp {
138
139
  customElements.define('girafe-tree-view-theme', TreeViewThemeComponent);
139
140
  customElements.define('girafe-user-preferences', UserPreferencesComponent);
140
141
  customElements.define('girafe-video-record', VideoRecordComponent);
142
+ customElements.define('girafe-fixed-dimension', FixedDimensionComponent);
141
143
  }
142
144
  async initializeServiceWorker() {
143
145
  try {