function TipTool(map, point, opt_options) {
	this.opts = opt_options || {};
	this.point = point;
	this.setMap(map);
	this.map = map;
};

// subclass of OverlayView()
TipTool.prototype = new google.maps.OverlayView();

/**
 * onAdd(). Called internally by API when added on map. to be called just once
 */
TipTool.prototype.onAdd = function() {
	this.div_ = document.createElement('div');
	this.div_.style.position = "absolute";
	this.div_.style.overflow = "hidden";
	this.zIndex = this.opts.zIndex || 0;
	this.div_.className = this.opts.cssClass || this.opts.className || 'tiptool';
	this.div_.innerHTML = this.opts.html || "";
	google.maps.event.addDomListener(this.div_, "click", function(event) {
		google.maps.event.trigger(me, "click", event);
	});
	var panes = this.getPanes();
	var paneId = this.opts.pane || "floatPane";
	panes[paneId].appendChild(this.div_);
	this.opacity = this.opts.opacity * 1 || 1;
	this.div_.style.filter = 'alpha(opacity:' + this.opacity * 100 + ')';
	this.div_.style.opacity = this.opacity;
	this.div_.style.display = "none";
}

/**
 * called internally by API when map moves.
 */
TipTool.prototype.draw = function() {
	var pixPoint = this.getProjection().fromLatLngToDivPixel(this.point);
	this.div_.style.left = pixPoint.x + 'px';
	this.div_.style.top = pixPoint.y + 'px';
	var SEx = pixPoint.x + this.div_.offsetWidth;
	var SEy = pixPoint.y + this.div_.offsetHeight;
	var pixSE = new google.maps.Point(SEx, SEy);
	this.opts.SE = this.getProjection().fromDivPixelToLatLng(pixSE);
	this.opts.point = this.point;
};

/**
 * Sets latLng position of tooltip
 * 
 * @param {LatLng}
 *            point The location where the TipTool shall be moved
 */

TipTool.prototype.setPosition = function(pint) {
	if (!this.div_)
		return false;
	this.point = pint;
	this.draw();
	return true
};
/**
 * Removes the div from DOM
 * 
 * @returns true if success, false if the div was not found
 */
TipTool.prototype.onRemove = function() {
	if (!this.div_)
		return false;
	this.div_.parentNode.removeChild(this.div_);
	this.div_ = null;
	return true;
};
/**
 * Sets the div display:none
 * 
 * @returns true if success, false if the div was not found
 */
TipTool.prototype.hide = function() {
	if (!this.div_)
		return false;
	this.div_.style.display = "none";
	return true;
};
/**
 * Sets the div display: block
 * 
 * @returns true if success, false if the div was not found
 */
TipTool.prototype.show = function() {
	if (!this.div_)
		return false;
	this.div_.style.display = "block";
	return true;
};

/**
 * Sets innerHTML of the div
 * 
 * @param {String}
 * @returns true if success, false if the div was not found
 */
TipTool.prototype.setContent = function(html) {
	if (!this.div_) {
		return false;
	}
	this.div_.innerHTML = html;
	return true;
};

/**
 * Copies properties of given options object to internal this.opts
 * 
 * @param optional
 *            object
 * @returns the updated internal this.opts object
 */
TipTool.prototype.props = function(options) { // needs work for more
												// properties
	var opts = options || {};
	for ( var prop in opts) {
		this.opts[prop] = opts[prop];
	}
	return this.opts;
};
/**
 * @returns The location of the div
 * @type LatLng object (null if the div was not found)
 */
TipTool.prototype.getPosition = function() {
	if (!this.div_)
		return null;
	return this.bounds_.getCenter();
};
/**
 * @returns True if TipTool is in viewport
 * @type boolean
 */
TipTool.prototype.isVisible = function() {
	var bounds = this.map.getBounds();
	var visible = (bounds.contains(this.opts.point) && bounds.contains(this.opts.SE));
	return visible;
};
/**
 * pans map to bring TipTool in viewport
 */
TipTool.prototype.bringVisible = function() {
	if (this.isVisible()) {
		this.map.setCenter(this.map.getCenter());
	} else {
		this.map.panTo(this.opts.point);
	}
};


