File: element.bs

package info (click to toggle)
storm-lang 0.7.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 52,004 kB
  • sloc: ansic: 261,462; cpp: 140,405; sh: 14,891; perl: 9,846; python: 2,525; lisp: 2,504; asm: 860; makefile: 678; pascal: 70; java: 52; xml: 37; awk: 12
file content (124 lines) | stat: -rw-r--r-- 2,977 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use ui;
use core:geometry;

/**
 * An element on a slide.
 */
class Element on Render {
	// Current position. Generally set by the layout.
	private Rect myPos;

	// Animations.
	private Animation[] myAni;

	// Visible at the last repaint?
	private Bool visibleLastRepaint;

	// Get/set the position.
	Rect pos() : final { myPos; }
	assign pos(Rect p) { myPos = p; }

	// Get the minimum size of this element.
	Size minSize() : abstract;

	// Initialize any animations in here.
	void setupAnimations(Presentation p) {
		for (a in animations) {
			a.setup(p, this);
		}
	}

	// Setup repaint notifications.
	void setupRepaint(Fn<void> callback) {}

	// Cleanup anything that needs to be cleaned up after the presentation is closed.
	void cleanup() {}

	// Quick check if this element is interactive.
	InteractiveElement? interactive() {
		null;
	}

	// Extract the animations from this element. Expected to be called once on slide setup, so might
	// be somewhat slow.
	Animation[] animations() { myAni; }

	// Add an animation.
	void animation(Animation a) {
		myAni << a;
	}

	// Draw, considering any animations in here.
	void draw(Graphics g, Nat step, Duration time) {
		if (before(g, step, time))
			draw(g);
		after(g, step, time);
	}

	// Draw this element at the location indicated by `pos`.
	void draw(Graphics g) : abstract;

	// Call if you need to re-implement 'draw'.
	protected Bool before(Graphics g, Nat step, Duration time) : final {
		Bool show = true;
		Nat count = myAni.count;
		for (Nat i = 0; i < count; i++) {
			show &= myAni[i].before(this, g, step, time);
		}
		visibleLastRepaint = show;
		show;
	}

	protected void after(Graphics g, Nat step, Duration time) : final {
		for (Nat i = myAni.count; i > 0; i--) {
			myAni[i - 1].after(this, g, step, time);
		}
	}

	// Was this item visible at the last repaint?
	// Used mainly for hit-tests for mouse coordinates.
	Bool visible() : final {
		visibleLastRepaint;
	}
}


/**
 * Element that the user can interact with.
 */
class InteractiveElement extends Element {
	// Called when the cursor is above the element. Return true if a repaint is needed.
	Bool mouseMoved(Point pt) { false; }

	// Called when the mouse was clicked above the element. Return true if a repaint is needed.
	Bool mouseClicked(Point pt, Bool down, MouseButton button) { false; }

	// Called when the mouse was double-clicked above the element. Return true if a repaint is needed.
	Bool mouseDblClicked(Point pt, MouseButton button) { false; }

	// Quick check if the element is interactive.
	InteractiveElement? interactive() : override {
		this;
	}
}


/**
 * Connect elements to the layout system.
 */
package class ElementWrap extends layout:Component {
	Element control;

	init(Element e) {
		init() { control = e; }
	}

	Rect pos() { control.pos; }
	assign pos(Rect p) { control.pos = p; }
	Size minSize() { control.minSize; }
}

// Tell the layout how to wrap things.
ElementWrap component(Element e) {
	ElementWrap(e);
}