2 # default delay (in seconds)
6 # @param size ([width, height])
7 new: func(size, id = nil)
10 parents: [Tooltip, PropertyElement.new(["/sim/gui/canvas", "window"], id)],
25 m.setInt("size[0]", size[0]);
26 m.setInt("size[1]", size[1]);
27 m.setBool("visible", 0);
28 m.setInt("z-index", gui.STACK_INDEX["tooltip"]);
30 m._hideTimer = maketimer(m.DELAY, m, Tooltip._hideTimeout);
31 m._hideTimer.singleShot = 1;
39 if( me["_canvas"] != nil )
42 # Create the canvas to be used for this Tooltip
44 # @return The new canvas
53 size: [2 * size[0], 2 * size[1]],
57 index: me._node.getIndex()
61 # don't do anything with mouse events ourselves
62 me.set("capture-events", 0);
63 me.set("fill", "rgba(255,255,255,0.8)");
65 # transparent background
66 me._canvas.setColorBackground(0.0, 0.0, 0.0, 0.0);
68 var root = me._canvas.createGroup();
72 root.createChild("image", "background")
73 .set("src", "gui/images/tooltip.png")
74 .set("slice", me._slice ~ " fill")
78 root.createChild("text", "tooltip-caption")
79 .setText("Aircraft Help")
80 .setAlignment("left-top")
82 .setFont("LiberationFonts/LiberationSans-Bold.ttf")
84 .setDrawMode(Text.TEXT)
85 .setTranslation(me._slice, me._slice)
86 .setMaxWidth(size[0]);
97 setProperty: func(prop)
99 if (me._property != nil)
100 removelistener(me._listener);
103 if (me._property != nil)
104 me._listener = setlistener(me._property, func { me._updateText(); });
109 # specify a string used to compute the width of the tooltip
110 setWidthText: func(txt)
112 me._measureBB = me._text.setText(txt)
121 if (me._property != nil) {
122 var val = me._property.getValue() or 0;
124 # https://code.google.com/p/flightgear-bugs/issues/detail?id=1454
125 # wrap mapping in 'call' to catch conversion errors
126 var val_mapped = call(me._remapValue, [val], me, nil, var err = []);
130 "Tooltip: failed to remap " ~ debug.string(me._property, 0) ~ ":\n"
131 ~ debug.string(err, 0)
134 msg = sprintf(me._label, val_mapped or val);
137 me._text.setText(msg);
143 var max_width = me.get("size[0]") - 2 * me._slice;
144 me._text.setMaxWidth(max_width);
147 var text_bb = me._text.update().getBoundingBox();
148 var width = text_bb[2];
149 var height = text_bb[3];
151 if( me._measureBB != nil )
153 width = math.max(width, me._measureBB[2]);
154 height = math.max(height, me._measureBB[3]);
157 if( width > max_width )
160 me._width = width + 2 * me._slice;
161 me._height = height + 2 * me._slice;
162 me._frame.setSize(me._width, me._height)
166 _remapValue: func(val)
168 if (me._mapping == "") return val;
169 if (me._mapping == "percent") return int(val * 100);
171 # TODO - translate me!
172 if (me._mapping == "on-off") return (val == 1) ? "ON" : "OFF";
173 if (me._mapping == "arm-disarm") return (val == 1) ? "ARMED" : "DISARMED";
175 # provide both 'senses' of the flag here
176 if (me._mapping == "up-down") return (val == 1) ? "UP" : "DOWN";
177 if (me._mapping == "down-up") return (val == 1) ? "DOWN" : "UP";
178 if (me._mapping == "open-close") return (val == 1) ? "OPEN" : "CLOSED";
179 if (me._mapping == "close-open") return (val == 1) ? "CLOSED" : "OPEN";
181 if (me._mapping == "heading") return geo.normdeg(val);
182 if (me._mapping == "nasal") return me._mappingFunc(val);
187 setMapping: func(mapping, f = nil)
189 me._mapping = mapping;
194 setTooltipId: func(tipId)
197 if ((tipId != nil) and me._hiding) {
198 me._hideTimer.stop();
203 getTooltipId: func { me._tipId; },
205 # Get the displayed canvas
208 return me['_canvas'];
211 setPosition: func(x, y)
213 me.setInt("x", x + 10);
214 me.setInt("y", y + 10);
219 # don't show if undefined
220 if (me._tipId == nil) return;
223 me._hideTimer.stop();
227 if (!me.isVisible()) {
228 me.setBool("visible", 1);
232 showMessage: func(timeout = nil, node = nil)
234 if(var y = me._haveNode(node, 'y') != nil ) {
237 me.setInt("y", getprop('/sim/startup/ysize') * 0.2);
239 if(var x = me._haveNode(node, 'x') != nil) {
242 var screenW = getprop('/sim/startup/xsize');
243 me.setInt("x", (screenW - me._width) * 0.5);
246 # https://code.google.com/p/flightgear-bugs/issues/detail?id=1273
247 # when tooltip is shown for some other reason, ensure it stays for
248 # the full delay (unless replaced). Don't allow the update-hover
249 # code path to hide() with the shorter delay.
251 me._hideTimer.restart(timeout or me.DELAY);
254 _haveNode: func(node, key) {
255 if(node == nil ) return nil;
256 var value = num(node.getValue(key) );
262 # this gets run repeatedly during mouse-moves
263 if (me._hiding) return;
266 me._hideTimer.restart(0.5);
271 me._hideTimer.stop();
277 return me.getBool("visible");
293 me.setBool("visible", 0);
298 var tooltip = canvas.Tooltip.new([300, 100]);
299 tooltip.createCanvas();
301 var innerSetTooltip = func(node)
303 tooltip.setLabel(cmdarg().getNode('label').getValue());
304 var measure = cmdarg().getNode('measure-text');
305 if (measure != nil) {
306 tooltip.setWidthText(measure.getValue());
308 tooltip.setWidthText(nil);
311 var propPath = cmdarg().getNode('property');
312 if (propPath != nil) {
313 var n = props.globals.getNode(propPath.getValue());
314 tooltip.setProperty(n);
316 tooltip.setProperty(nil);
319 var mapping = cmdarg().getNode('mapping');
320 if (mapping != nil) {
321 var m = mapping.getValue();
324 f = compile(cmdarg().getNode('script').getValue());
327 tooltip.setMapping(m, f);
329 tooltip.setMapping(nil);
333 var setTooltip = func(node)
335 var tipId = cmdarg().getNode('tooltip-id').getValue();
336 if (tooltip.getTooltipId() == tipId) {
337 return; # nothing more to do
340 var x = cmdarg().getNode('x').getValue();
341 var y = cmdarg().getNode('y').getValue();
343 var screenHeight = getprop('/sim/startup/ysize');
344 tooltip.setPosition(x, screenHeight - y);
345 tooltip.setTooltipId(tipId);
346 innerSetTooltip(node);
348 # don't actually show here, we do that response to tooltip-timeout
349 # so this is just getting ready
352 var showTooltip = func(node)
354 var r = node.getNode("reason");
355 if ((r != nil) and (r.getValue() == "click")) {
356 # click triggering tooltip, show immediately
363 var updateHover = func(node)
365 tooltip.setTooltipId(nil);
367 # if not shown, nothing to do here
368 if (!tooltip.isVisible()) return;
370 # reset cursor to standard
375 var showMessage = func(node)
377 var msgId = node.getNode("id");
378 tooltip.setTooltipId((msgId == nil) ? 'msg' : msgId.getValue());
379 innerSetTooltip(node);
381 var timeout = node.getNode("delay");
382 tooltip.showMessage( timeout != nil ? timeout.getValue() : nil, node);
385 var clearMessage = func(node)
387 var msgId = node.getNode("id");
388 if (tooltip.getTooltipId() != msgId.getValue()) return;
392 addcommand("update-hover", updateHover);
393 addcommand("set-tooltip", setTooltip);
394 addcommand("tooltip-timeout", showTooltip);
395 addcommand("show-message", showMessage);
396 addcommand("clear-message", clearMessage);