@yuneta/gobj-ui 7.23.18 → 7.23.20

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.
@@ -39,6 +39,8 @@ import {createElement2, gobj_send_event} from "@yuneta/gobj-js";
39
39
 
40
40
  import {t} from "i18next";
41
41
 
42
+ import {set_pressed_state} from "./lib_graph.js";
43
+
42
44
 
43
45
  /************************************************************
44
46
  * One icon button that fires `event_name`.
@@ -141,6 +143,99 @@ export function yui_graph_fold_items(gobj, wide)
141
143
  ];
142
144
  }
143
145
 
146
+ /************************************************************
147
+ * The ANCHOR toggle: pick one element and every camera move
148
+ * from then on leaves it in the MIDDLE.
149
+ *
150
+ * Why it exists: a graph that fits on screen is unreadable at
151
+ * the zoom that makes it fit, and the zoom that makes it
152
+ * readable does not fit -- so the useful view is always a
153
+ * fraction of the document, and which fraction is the whole
154
+ * question. Without an anchor, `1:1` lands wherever the
155
+ * layout's origin happens to be and the reader hunts for the
156
+ * node they were looking at.
157
+ *
158
+ * Crosshairs and not a thumbtack. A tack says "do not move
159
+ * this", which is what a pinned NODE would mean in a graph you
160
+ * can drag nodes around in; this pins the CAMERA to a target,
161
+ * which is what a crosshair says and what every map that
162
+ * offers it draws. It is also in the icon set already, and a
163
+ * `yi-*` class that is not is a black square.
164
+ *
165
+ * Three states, because two would not say what a press does:
166
+ *
167
+ * off no target; the camera behaves as it always did
168
+ * arming waiting for you to click the element you mean
169
+ * on locked; every zoom re-centres on it
170
+ ************************************************************/
171
+ export function yui_graph_anchor_item(gobj, wide)
172
+ {
173
+ return camera_button(gobj, "yi-location-crosshairs", "EV_TOGGLE_ANCHOR",
174
+ "anchor view", wide);
175
+ }
176
+
177
+ /************************************************************
178
+ * Paint the anchor button. `state` is "off" | "arming" | "on".
179
+ *
180
+ * Both live states look PRESSED, because both are states the
181
+ * control is IN rather than actions; what separates them is the
182
+ * colour, and only the waiting one takes a palette colour --
183
+ * it is the one that needs the reader to do something next.
184
+ ************************************************************/
185
+ export function yui_graph_update_anchor($container, state)
186
+ {
187
+ if(!$container) {
188
+ return;
189
+ }
190
+ let $btn = $container.querySelector('.EV_TOGGLE_ANCHOR');
191
+ if(!$btn) {
192
+ return; /* a toolbar without the control: nothing to paint */
193
+ }
194
+ set_pressed_state($container, '.EV_TOGGLE_ANCHOR', state !== "off");
195
+ $btn.classList.toggle('color_pending_state', state === "arming");
196
+ $btn.setAttribute("aria-pressed", (state === "on")? "true": "false");
197
+
198
+ let key = (state === "arming")? "click the element to centre on"
199
+ : (state === "on")? "centred: click to release"
200
+ : "anchor view";
201
+ $btn.setAttribute("title", t(key));
202
+ $btn.setAttribute("data-i18n-title", key);
203
+ $btn.setAttribute("aria-label", t(key));
204
+ $btn.setAttribute("data-i18n-aria-label", key);
205
+ }
206
+
207
+ /************************************************************
208
+ * Put `node_id` back in the middle of the viewport.
209
+ *
210
+ * Called AFTER the camera moved, never instead of moving it:
211
+ * the zoom is what the reader asked for, the centring is what
212
+ * keeps the thing they are reading under their eyes.
213
+ *
214
+ * Guarded on every side because it runs on every wheel notch:
215
+ * a graph mid-rebuild, an anchor whose node went away with a
216
+ * fold, a G6 version without `focusElement` -- none of those is
217
+ * an error worth a log line per notch, they are all "there is
218
+ * nothing to centre right now".
219
+ ************************************************************/
220
+ export function yui_graph_center_on(graph, node_id)
221
+ {
222
+ if(!graph || !node_id) {
223
+ return false;
224
+ }
225
+ try {
226
+ if(typeof graph.getElementData === "function" && !graph.getElementData(node_id)) {
227
+ return false;
228
+ }
229
+ if(typeof graph.focusElement !== "function") {
230
+ return false;
231
+ }
232
+ graph.focusElement(node_id);
233
+ return true;
234
+ } catch(e) {
235
+ return false; /* the element is gone, or the graph is between renders */
236
+ }
237
+ }
238
+
144
239
  /************************************************************
145
240
  * A refresh button, for the graphs that offer one.
146
241
  ************************************************************/