/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */

const Clutter = imports.gi.Clutter;
const Lang = imports.lang;
const Signals = imports.signals;

// Link is a clickable link. Right now it just handles properly capturing
// press and release events and short-circuiting the button handling in
// ClutterText, but more features like different colors for hover/pressed states
// or a different mouse cursor could be implemented.
//
// The properties passed in are forwarded to the Clutter.Text() constructor,
// so can include, 'text', 'font_name', etc.
function Link(props) {
    this._init(props);
}

Link.prototype = {
    _init : function(props) {
	let realProps = { reactive: true };
        // The user can pass in reactive: false to override the above and get
        // a non-reactive link (a link to the current page, perhaps)
	Lang.copyProperties(props, realProps);

	this.actor = new Clutter.Text(realProps);
	this.actor._delegate = this;
	this.actor.connect('button-press-event', Lang.bind(this, this._onButtonPress));
	this.actor.connect('button-release-event', Lang.bind(this, this._onButtonRelease));
	this.actor.connect('enter-event', Lang.bind(this, this._onEnter));
	this.actor.connect('leave-event', Lang.bind(this, this._onLeave));

	this._buttonDown = false;
	this._havePointer = false;
    },

    // Update the text of the link
    setText : function(text) {
	this.actor.text = text;
    },

    // We want to react on buttonDown, but if we override button-release-event for
    // ClutterText, but not button-press-event, we get a stuck grab. Tracking
    // buttonDown and doing the grab isn't really necessary, but doing it makes
    // the behavior perfectly correct if the user clicks on one actor, drags
    // to another and releases - that should not trigger either actor.
    _onButtonPress : function(actor, event) {
	this._buttonDown = true;
	this._havePointer = true; // Hack to work around poor enter/leave tracking in Clutter
	Clutter.grab_pointer(actor);

	return true;
    },

    _onButtonRelease : function(actor, event) {
	if (this._buttonDown) {
	    this._buttonDown = false;
	    Clutter.ungrab_pointer(actor);

	    if (this._havePointer)
		this.emit('clicked');
	}

	return true;
    },

    _onEnter : function(actor, event) {
	if (event.get_source() == actor)
	    this._havePointer = true;

        return false;
    },

    _onLeave : function(actor, event) {
	if (event.get_source() == actor)
	    this._havePointer = false;

        return false;
    }
};

Signals.addSignalMethods(Link.prototype);