function Preview(parentNode, family, style, text) {
	this.mark(family, style);
	this.parentNode = parentNode;
	this.family = family;
	this.style = style;
	this.updating = false;
	this.text = text;
	this.install();
	this.redraw();
}

// Marks a certain combination of family and a style
// used, so that the client code can automatically choose
// fonts and styles that are not displayed yet.
Preview.prototype.mark = function(family, style) {
	var map = Preview.used;
	if (map[family] == null)
		map[family] = {};
	if (map[family][style] == null)
		map[family][style] = 0;
	map[family][style]++;
}

// Unmarks the current font and style.
Preview.prototype.unmark = function() {
	var map = Preview.used;
	map[this.family][this.style]--;
	var empty = true;
	for (var key in map[this.family]) {
		if (map[this.family][key] > 0)
			empty = false;
	}
	if (empty)
		map[this.family] = null;
}

/*
	<parentNode>
		<div class="preview [updating]">
			<img src="render.cgi?..."/>
			<img id="loading" src="..."/>
		</div>
	</parentNode>
*/
Preview.prototype.install = function() {
	// Main wrapper for the whole preview pane
	this.wrapper = document.createElement("div");
	this.wrapper.className = "preview";
	// Image with the rendered text
	this.image = document.createElement("img");
	this.wrapper.appendChild(this.image);
	// Link to the parent node
	this.parentNode.appendChild(this.wrapper);
}

Preview.prototype.setText = function(t) {
	this.text = t;
	this.redraw();
}

Preview.prototype.setStyle = function(s) {
	this.unmark();
	this.mark(this.family, s);
	this.style = s;
	this.redraw();
}

Preview.prototype.setFont = function(f, s) {
	this.unmark();
	this.mark(f, s);
	this.family = f;
	this.style = s;
	this.redraw();
}

Preview.prototype.redraw = function() {
	if (this.updating)
		return;
	this.updating = true;
	this.wrapper.className += " updating";
	this.renderedText = this.text;
	var img = new Image();
	var preview = this;
	img.onload = function() {
		preview.wrapper.replaceChild(this, preview.image);
		preview.image = this;
		preview.wrapper.className = preview.wrapper.className.replace(" updating", "");
		preview.updating = false;
		// If the sample text changed during
		// the redraw, we’ll schedule another redraw.
		if (preview.renderedText != preview.text)
			preview.redraw();
	}
	img.src = URL_PREFIX+"/render.cgi"
		+ "?t=" + encodeURIComponent(this.text)
		+ '&f=' + encodeURIComponent(this.family)
		+ '&s=' + encodeURIComponent(this.style);
}

// Used without accessor by Controls.js, watch out.
Preview.used = {};
