<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file motor_ramp.cpp
 * Application to test motor ramp up.
 *
 * @author Andreas Antener <andreas@uaventure.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <px4_config.h>
#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_posix.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <poll.h>

#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_pwm_output.h>
#include <platforms/px4_defines.h>

#include "systemlib/systemlib.h"
#include "systemlib/err.h"

enum RampState {
	RAMP_INIT,
	RAMP_MIN,
	RAMP_RAMP,
	RAMP_WAIT
};

enum Mode {
	RAMP,
	SINE,
	SQUARE
};

static bool _thread_should_exit = false;		/**< motor_ramp exit flag */
static bool _thread_running = false;		/**< motor_ramp status flag */
static int _motor_ramp_task;				/**< Handle of motor_ramp task / thread */
static float _ramp_time;
static int _min_pwm;
static int _max_pwm;
static Mode _mode;
static char *_mode_c;

/**
 * motor_ramp management function.
 */
extern "C" __EXPORT int motor_ramp_main(int argc, char *argv[]);

/**
 * Mainloop of motor_ramp.
 */
int motor_ramp_thread_main(int argc, char *argv[]);

bool min_pwm_valid(unsigned pwm_value);

bool max_pwm_valid(unsigned pwm_value);

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value);

int set_out(int fd, unsigned long max_channels, float output);

int prepare(int fd, unsigned long *max_channels);

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_WARN("\n\nWARNING: motors will ramp up to full speed!\n\n"
		 "Usage: motor_ramp <mode> <min_pwm> <time> [<max_pwm>]\n"
		 "<mode> can be one of (ramp|sine|square)\n\n"
		 "Example:\n"
		 "sdlog2 on\n"
		 "mc_att_control stop\n"
		 "fw_att_control stop\n"
		 "motor_ramp sine 1100 0.5\n");
}

/**
 * The motor_ramp app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int motor_ramp_main(int argc, char *argv[])
{
	if (argc < 4) {
		usage("missing parameters");
		return 1;
	}

	if (_thread_running) {
		PX4_WARN("motor_ramp already running\n");
		/* this is not an error */
		return 0;
	}

	if (!strcmp(argv[1], "ramp")) {
		_mode = RAMP;

	} else if (!strcmp(argv[1], "sine")) {
		_mode = SINE;

	} else if (!strcmp(argv[1], "square")) {
		_mode = SQUARE;

	} else {
		usage("selected mode not valid");
		return 1;
	}

	_mode_c = argv[1];

	_min_pwm = atoi(argv[2]);

	if (!min_pwm_valid(_min_pwm)) {
		usage("min PWM not in range");
		return 1;
	}

	_ramp_time = atof(argv[3]);

	if (argc > 4) {
		_max_pwm = atoi(argv[4]);

		if (!max_pwm_valid(_max_pwm)) {
			usage("max PWM not in range");
			return 1;
		}

	} else {
		_max_pwm = 2000;
	}

	if (!(_ramp_time > 0)) {
		usage("ramp time must be greater than 0");
		return 1;
	}

	_thread_should_exit = false;
	_motor_ramp_task = px4_task_spawn_cmd("motor_ramp",
					      SCHED_DEFAULT,
					      SCHED_PRIORITY_DEFAULT + 40,
					      2000,
					      motor_ramp_thread_main,
					      (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
	return 0;

	usage("unrecognized command");
	return 1;
}

bool min_pwm_valid(unsigned pwm_value)
{
	return pwm_value >= 900 && pwm_value <= 1500;
}

bool max_pwm_valid(unsigned pwm_value)
{
	return pwm_value <= 2100 && pwm_value > _min_pwm;
}

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value)
{
	int ret;

	struct pwm_output_values pwm_values;
	memset(&pwm_values, 0, sizeof(pwm_values));

	pwm_values.channel_count = max_channels;

	for (int i = 0; i < max_channels; i++) {
		pwm_values.values[i] = pwm_value;
	}

	ret = px4_ioctl(fd, PWM_SERVO_SET_MIN_PWM, (long unsigned int)&pwm_values);

	if (ret != OK) {
		PX4_ERR("failed setting min values");
		return 1;
	}

	return 0;
}

int set_out(int fd, unsigned long max_channels, float output)
{
	int ret;
	int pwm = (_max_pwm - _min_pwm) * output + _min_pwm;

	for (unsigned i = 0; i < max_channels; i++) {

		ret = ioctl(fd, PWM_SERVO_SET(i), pwm);

		if (ret != OK) {
			PX4_ERR("PWM_SERVO_SET(%d), value: %d", i, pwm);
			return 1;
		}
	}

	return 0;
}

int prepare(int fd, unsigned long *max_channels)
{
	/* make sure no other source is publishing control values now */
	struct actuator_controls_s actuators;
	int act_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);

	/* clear changed flag */
	orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, act_sub, &actuators);

	/* wait 50 ms */
	usleep(50000);

	/* now expect nothing changed on that topic */
	bool orb_updated;
	orb_check(act_sub, &orb_updated);

	if (orb_updated) {
		PX4_ERR("ABORTING! Attitude control still active. Please ensure to shut down all controllers:\n"
			"\tmc_att_control stop\n"
			"\tfw_att_control stop\n");
		return 1;
	}

	/* get number of channels available on the device */
	if (px4_ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)max_channels) != OK) {
		PX4_ERR("PWM_SERVO_GET_COUNT");
		return 1;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_ARM_OK");
		return 1;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		PX4_ERR("PWM_SERVO_ARM");
		return 1;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_FORCE_SAFETY_OFF");
		return 1;
	}

	return 0;
}

int motor_ramp_thread_main(int argc, char *argv[])
{
	_thread_running = true;

	char *dev = PWM_OUTPUT0_DEVICE_PATH;
	unsigned long max_channels = 0;

	int fd = px4_open(dev, 0);

	if (fd < 0) {
		PX4_ERR("can't open %s", dev);
	}

	if (prepare(fd, &max_channels) != OK) {
		_thread_should_exit = true;
	}

	set_out(fd, max_channels, 0.0f);

	float dt = 0.001f; // prevent division with 0
	float timer = 0.0f;
	hrt_abstime start = 0;
	hrt_abstime last_run = 0;

	enum RampState ramp_state = RAMP_INIT;
	float output = 0.0f;

	while (!_thread_should_exit) {

		if (last_run > 0) {
			dt = hrt_elapsed_time(&last_run) * 1e-6;

		} else {
			start = hrt_absolute_time();
		}

		last_run = hrt_absolute_time();
		timer = hrt_elapsed_time(&start) * 1e-6;

		switch (ramp_state) {
		case RAMP_INIT: {
				PX4_WARN("setting pwm min: %d", _min_pwm);
				set_min_pwm(fd, max_channels, _min_pwm);
				ramp_state = RAMP_MIN;
				break;
			}

		case RAMP_MIN: {
				if (timer > 3.0f) {
					PX4_WARN("starting %s: %.2f sec", _mode_c, (double)_ramp_time);
					start = hrt_absolute_time();
					ramp_state = RAMP_RAMP;
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_RAMP: {
				if (_mode == RAMP) {
					output += 1000.0f * dt / (_max_pwm - _min_pwm) / _ramp_time;

				} else if (_mode == SINE) {
					// sine outpout with period T = _ramp_time and magnitude between [0,1]
					// phase shift makes sure that it starts at zero when timer is zero
					output = 0.5f * (1.0f + sinf(M_TWOPI_F * timer / _ramp_time - M_PI_2_F));

				} else if (_mode == SQUARE) {
					output = fmodf(timer, _ramp_time) > (_ramp_time * 0.5f) ? 1.0f : 0.0f;
				}

				if ((output > 1.0f && _mode == RAMP) || (timer > 3.0f * _ramp_time)) {
					// for ramp mode we set output to 1, for others we just leave it as is
					output = _mode != RAMP ? output : 1.0f;
					start = hrt_absolute_time();
					ramp_state = RAMP_WAIT;
					PX4_WARN("%s finished, waiting", _mode_c);
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_WAIT: {
				if (timer > 1.0f) {
					_thread_should_exit = true;
					PX4_WARN("stopping");
					break;
				}

				set_out(fd, max_channels, output);
				break;
			}
		}

		// rate limit
		usleep(2000);
	}

	if (fd >= 0) {
		/* disarm */
		ioctl(fd, PWM_SERVO_DISARM, 0);

		px4_close(fd);
	}

	_thread_running = false;

	return 0;
}
<commit_msg>reduced the wait time at the end of the motor ramp to not unnecessary stress the system<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file motor_ramp.cpp
 * Application to test motor ramp up.
 *
 * @author Andreas Antener <andreas@uaventure.com>
 * @author Roman Bapst <bapstroman@gmail.com>
 */

#include <px4_config.h>
#include <px4_defines.h>
#include <px4_tasks.h>
#include <px4_posix.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <math.h>
#include <poll.h>

#include <arch/board/board.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_pwm_output.h>
#include <platforms/px4_defines.h>

#include "systemlib/systemlib.h"
#include "systemlib/err.h"

enum RampState {
	RAMP_INIT,
	RAMP_MIN,
	RAMP_RAMP,
	RAMP_WAIT
};

enum Mode {
	RAMP,
	SINE,
	SQUARE
};

static bool _thread_should_exit = false;		/**< motor_ramp exit flag */
static bool _thread_running = false;		/**< motor_ramp status flag */
static int _motor_ramp_task;				/**< Handle of motor_ramp task / thread */
static float _ramp_time;
static int _min_pwm;
static int _max_pwm;
static Mode _mode;
static char *_mode_c;

/**
 * motor_ramp management function.
 */
extern "C" __EXPORT int motor_ramp_main(int argc, char *argv[]);

/**
 * Mainloop of motor_ramp.
 */
int motor_ramp_thread_main(int argc, char *argv[]);

bool min_pwm_valid(unsigned pwm_value);

bool max_pwm_valid(unsigned pwm_value);

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value);

int set_out(int fd, unsigned long max_channels, float output);

int prepare(int fd, unsigned long *max_channels);

/**
 * Print the correct usage.
 */
static void usage(const char *reason);

static void
usage(const char *reason)
{
	if (reason) {
		PX4_ERR("%s", reason);
	}

	PX4_WARN("\n\nWARNING: motors will ramp up to full speed!\n\n"
		 "Usage: motor_ramp <mode> <min_pwm> <time> [<max_pwm>]\n"
		 "<mode> can be one of (ramp|sine|square)\n\n"
		 "Example:\n"
		 "sdlog2 on\n"
		 "mc_att_control stop\n"
		 "fw_att_control stop\n"
		 "motor_ramp sine 1100 0.5\n");
}

/**
 * The motor_ramp app only briefly exists to start
 * the background job. The stack size assigned in the
 * Makefile does only apply to this management task.
 *
 * The actual stack size should be set in the call
 * to task_create().
 */
int motor_ramp_main(int argc, char *argv[])
{
	if (argc < 4) {
		usage("missing parameters");
		return 1;
	}

	if (_thread_running) {
		PX4_WARN("motor_ramp already running\n");
		/* this is not an error */
		return 0;
	}

	if (!strcmp(argv[1], "ramp")) {
		_mode = RAMP;

	} else if (!strcmp(argv[1], "sine")) {
		_mode = SINE;

	} else if (!strcmp(argv[1], "square")) {
		_mode = SQUARE;

	} else {
		usage("selected mode not valid");
		return 1;
	}

	_mode_c = argv[1];

	_min_pwm = atoi(argv[2]);

	if (!min_pwm_valid(_min_pwm)) {
		usage("min PWM not in range");
		return 1;
	}

	_ramp_time = atof(argv[3]);

	if (argc > 4) {
		_max_pwm = atoi(argv[4]);

		if (!max_pwm_valid(_max_pwm)) {
			usage("max PWM not in range");
			return 1;
		}

	} else {
		_max_pwm = 2000;
	}

	if (!(_ramp_time > 0)) {
		usage("ramp time must be greater than 0");
		return 1;
	}

	_thread_should_exit = false;
	_motor_ramp_task = px4_task_spawn_cmd("motor_ramp",
					      SCHED_DEFAULT,
					      SCHED_PRIORITY_DEFAULT + 40,
					      2000,
					      motor_ramp_thread_main,
					      (argv) ? (char *const *)&argv[2] : (char *const *)NULL);
	return 0;

	usage("unrecognized command");
	return 1;
}

bool min_pwm_valid(unsigned pwm_value)
{
	return pwm_value >= 900 && pwm_value <= 1500;
}

bool max_pwm_valid(unsigned pwm_value)
{
	return pwm_value <= 2100 && pwm_value > _min_pwm;
}

int set_min_pwm(int fd, unsigned long max_channels, unsigned pwm_value)
{
	int ret;

	struct pwm_output_values pwm_values;
	memset(&pwm_values, 0, sizeof(pwm_values));

	pwm_values.channel_count = max_channels;

	for (int i = 0; i < max_channels; i++) {
		pwm_values.values[i] = pwm_value;
	}

	ret = px4_ioctl(fd, PWM_SERVO_SET_MIN_PWM, (long unsigned int)&pwm_values);

	if (ret != OK) {
		PX4_ERR("failed setting min values");
		return 1;
	}

	return 0;
}

int set_out(int fd, unsigned long max_channels, float output)
{
	int ret;
	int pwm = (_max_pwm - _min_pwm) * output + _min_pwm;

	for (unsigned i = 0; i < max_channels; i++) {

		ret = ioctl(fd, PWM_SERVO_SET(i), pwm);

		if (ret != OK) {
			PX4_ERR("PWM_SERVO_SET(%d), value: %d", i, pwm);
			return 1;
		}
	}

	return 0;
}

int prepare(int fd, unsigned long *max_channels)
{
	/* make sure no other source is publishing control values now */
	struct actuator_controls_s actuators;
	int act_sub = orb_subscribe(ORB_ID_VEHICLE_ATTITUDE_CONTROLS);

	/* clear changed flag */
	orb_copy(ORB_ID_VEHICLE_ATTITUDE_CONTROLS, act_sub, &actuators);

	/* wait 50 ms */
	usleep(50000);

	/* now expect nothing changed on that topic */
	bool orb_updated;
	orb_check(act_sub, &orb_updated);

	if (orb_updated) {
		PX4_ERR("ABORTING! Attitude control still active. Please ensure to shut down all controllers:\n"
			"\tmc_att_control stop\n"
			"\tfw_att_control stop\n");
		return 1;
	}

	/* get number of channels available on the device */
	if (px4_ioctl(fd, PWM_SERVO_GET_COUNT, (unsigned long)max_channels) != OK) {
		PX4_ERR("PWM_SERVO_GET_COUNT");
		return 1;
	}

	/* tell IO/FMU that its ok to disable its safety with the switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_ARM_OK, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_ARM_OK");
		return 1;
	}

	/* tell IO/FMU that the system is armed (it will output values if safety is off) */
	if (px4_ioctl(fd, PWM_SERVO_ARM, 0) != OK) {
		PX4_ERR("PWM_SERVO_ARM");
		return 1;
	}

	/* tell IO to switch off safety without using the safety switch */
	if (px4_ioctl(fd, PWM_SERVO_SET_FORCE_SAFETY_OFF, 0) != OK) {
		PX4_ERR("PWM_SERVO_SET_FORCE_SAFETY_OFF");
		return 1;
	}

	return 0;
}

int motor_ramp_thread_main(int argc, char *argv[])
{
	_thread_running = true;

	char *dev = PWM_OUTPUT0_DEVICE_PATH;
	unsigned long max_channels = 0;

	int fd = px4_open(dev, 0);

	if (fd < 0) {
		PX4_ERR("can't open %s", dev);
	}

	if (prepare(fd, &max_channels) != OK) {
		_thread_should_exit = true;
	}

	set_out(fd, max_channels, 0.0f);

	float dt = 0.001f; // prevent division with 0
	float timer = 0.0f;
	hrt_abstime start = 0;
	hrt_abstime last_run = 0;

	enum RampState ramp_state = RAMP_INIT;
	float output = 0.0f;

	while (!_thread_should_exit) {

		if (last_run > 0) {
			dt = hrt_elapsed_time(&last_run) * 1e-6;

		} else {
			start = hrt_absolute_time();
		}

		last_run = hrt_absolute_time();
		timer = hrt_elapsed_time(&start) * 1e-6;

		switch (ramp_state) {
		case RAMP_INIT: {
				PX4_WARN("setting pwm min: %d", _min_pwm);
				set_min_pwm(fd, max_channels, _min_pwm);
				ramp_state = RAMP_MIN;
				break;
			}

		case RAMP_MIN: {
				if (timer > 3.0f) {
					PX4_WARN("starting %s: %.2f sec", _mode_c, (double)_ramp_time);
					start = hrt_absolute_time();
					ramp_state = RAMP_RAMP;
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_RAMP: {
				if (_mode == RAMP) {
					output += 1000.0f * dt / (_max_pwm - _min_pwm) / _ramp_time;

				} else if (_mode == SINE) {
					// sine outpout with period T = _ramp_time and magnitude between [0,1]
					// phase shift makes sure that it starts at zero when timer is zero
					output = 0.5f * (1.0f + sinf(M_TWOPI_F * timer / _ramp_time - M_PI_2_F));

				} else if (_mode == SQUARE) {
					output = fmodf(timer, _ramp_time) > (_ramp_time * 0.5f) ? 1.0f : 0.0f;
				}

				if ((output > 1.0f && _mode == RAMP) || (timer > 3.0f * _ramp_time)) {
					// for ramp mode we set output to 1, for others we just leave it as is
					output = _mode != RAMP ? output : 1.0f;
					start = hrt_absolute_time();
					ramp_state = RAMP_WAIT;
					PX4_WARN("%s finished, waiting", _mode_c);
				}

				set_out(fd, max_channels, output);
				break;
			}

		case RAMP_WAIT: {
				if (timer > 0.5f) {
					_thread_should_exit = true;
					PX4_WARN("stopping");
					break;
				}

				set_out(fd, max_channels, output);
				break;
			}
		}

		// rate limit
		usleep(2000);
	}

	if (fd >= 0) {
		/* disarm */
		ioctl(fd, PWM_SERVO_DISARM, 0);

		px4_close(fd);
	}

	_thread_running = false;

	return 0;
}
<|endoftext|>


<commit_before>#include "KVNetworkReply.h"

#include <QNetworkAccessManager>
#include <QBuffer>
#include <QTimer>
#include <QNetworkReply>
#include <QSslConfiguration>

#include "KVNetworkAccessManager.h"
#include "KVTranslator.h"

struct KVNetworkReplyPrivate {
	QNetworkReply *copied;

	QByteArray content;
	qint64 offset;
	bool translate;
	bool finished;

	QNetworkAccessManager *manager;
};

KVNetworkReply::KVNetworkReply(QObject *parent, QNetworkReply *toCopy,
                               QNetworkAccessManager *mgr, bool translate) :
	QNetworkReply(parent) {
	d = new KVNetworkReplyPrivate;
	d->finished = false;
	d->copied = toCopy;
	d->manager = mgr;
	d->translate = translate;

	setOperation(d->copied->operation());
	setRequest(d->copied->request());
	setUrl(d->copied->url());

	// Translate reply when it's complete
	connect(d->copied, SIGNAL(finished()), SLOT(handleResponse()));

	connect(d->copied, SIGNAL(encrypted()), SIGNAL(encrypted()));
	connect(d->copied, SIGNAL(metaDataChanged()), SIGNAL(metaDataChanged()));
}

KVNetworkReply::~KVNetworkReply() {
	delete d;
}

void KVNetworkReply::copyAttribute(QNetworkRequest::Attribute attr) {
	QVariant attribute = d->copied->attribute(attr);
	if(attribute.isValid())
		setAttribute(attr, attribute);
}

void KVNetworkReply::handleResponse() {
	if(d->finished) return;

	setError(d->copied->error(), d->copied->errorString());

	copyAttribute(QNetworkRequest::HttpStatusCodeAttribute);
	copyAttribute(QNetworkRequest::HttpReasonPhraseAttribute);
	copyAttribute(QNetworkRequest::RedirectionTargetAttribute);
	copyAttribute(QNetworkRequest::ConnectionEncryptedAttribute);
	copyAttribute(QNetworkRequest::SourceIsFromCacheAttribute);
	copyAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute);

	QList<QNetworkReply::RawHeaderPair> headers = d->copied->rawHeaderPairs();
	for(int i = 0; i < headers.size(); i++)
		setRawHeader(headers[i].first, headers[i].second);

	QString data = d->copied->readAll();
	d->copied->abort();

	//qDebug() << "content:" << data;

	if(d->translate)
		data = KVTranslator::instance()->translateJson(data).toUtf8();

	d->content = data.toUtf8();
	d->offset = 0;
	setHeader(QNetworkRequest::ContentLengthHeader, QVariant(d->content.size()));

	QNetworkRequest toolReq(QUrl("http://localhost:54321").resolved(url().path()));
	toolReq.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/json"));
	d->manager->post(toolReq, d->content);

	open(ReadOnly | Unbuffered);
	//qDebug() << "translated:" << d->content.constData();

	d->finished = true;

	emit finished();
	emit readChannelFinished();
}

qint64 KVNetworkReply::bytesAvailable() const {
	return d->content.size() - d->offset + QIODevice::bytesAvailable();
}

qint64 KVNetworkReply::readData(char *data, qint64 maxSize) {
	if (d->offset >= d->content.size())
		return -1;

	qint64 numBytes = qMin(maxSize, d->content.size() - d->offset);
	memcpy(data, d->content.constData() + d->offset, numBytes);
	d->offset += numBytes;

	return numBytes;
}

/*
 * Pass all these through to the underlying 'copied' QNetworkRequest because
 * There isn't a copy constructor. I now understand why everything in the
 * standard libraries has a copy constructor...
 */
void KVNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) {
	d->copied->ignoreSslErrors(errors);
}

QNetworkAccessManager* KVNetworkReply::manager() const {
	return d->copied->manager();
}

void KVNetworkReply::setSslConfiguration(const QSslConfiguration &config) {
	d->copied->setSslConfiguration(config);
}

QSslConfiguration KVNetworkReply::sslConfiguration() const {
	return d->copied->sslConfiguration();
}

bool KVNetworkReply::event(QEvent *e) {
	return d->copied->event(e);
}

void KVNetworkReply::abort() {
	d->finished = true; d->copied->abort();
}

void KVNetworkReply::ignoreSslErrors() {
	d->copied->ignoreSslErrors();
}

bool KVNetworkReply::isSequential() const {
	return true;
}
<commit_msg>Don't translate data before it's sent to the client<commit_after>#include "KVNetworkReply.h"

#include <QNetworkAccessManager>
#include <QBuffer>
#include <QTimer>
#include <QNetworkReply>
#include <QSslConfiguration>

#include "KVNetworkAccessManager.h"
#include "KVTranslator.h"

struct KVNetworkReplyPrivate {
	QNetworkReply *copied;

	QByteArray content;
	qint64 offset;
	bool translate;
	bool finished;

	QNetworkAccessManager *manager;
};

KVNetworkReply::KVNetworkReply(QObject *parent, QNetworkReply *toCopy,
                               QNetworkAccessManager *mgr, bool translate) :
	QNetworkReply(parent) {
	d = new KVNetworkReplyPrivate;
	d->finished = false;
	d->copied = toCopy;
	d->manager = mgr;
	d->translate = translate;

	setOperation(d->copied->operation());
	setRequest(d->copied->request());
	setUrl(d->copied->url());

	// Translate reply when it's complete
	connect(d->copied, SIGNAL(finished()), SLOT(handleResponse()));

	connect(d->copied, SIGNAL(encrypted()), SIGNAL(encrypted()));
	connect(d->copied, SIGNAL(metaDataChanged()), SIGNAL(metaDataChanged()));
}

KVNetworkReply::~KVNetworkReply() {
	delete d;
}

void KVNetworkReply::copyAttribute(QNetworkRequest::Attribute attr) {
	QVariant attribute = d->copied->attribute(attr);
	if(attribute.isValid())
		setAttribute(attr, attribute);
}

void KVNetworkReply::handleResponse() {
	if(d->finished) return;

	setError(d->copied->error(), d->copied->errorString());

	copyAttribute(QNetworkRequest::HttpStatusCodeAttribute);
	copyAttribute(QNetworkRequest::HttpReasonPhraseAttribute);
	copyAttribute(QNetworkRequest::RedirectionTargetAttribute);
	copyAttribute(QNetworkRequest::ConnectionEncryptedAttribute);
	copyAttribute(QNetworkRequest::SourceIsFromCacheAttribute);
	copyAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute);

	QList<QNetworkReply::RawHeaderPair> headers = d->copied->rawHeaderPairs();
	for(int i = 0; i < headers.size(); i++)
		setRawHeader(headers[i].first, headers[i].second);

	QString data = d->copied->readAll();
	d->copied->abort();

	//qDebug() << "content:" << data;

	QNetworkRequest toolReq(QUrl("http://localhost:54321").resolved(url().path()));
	toolReq.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/json"));
	d->manager->post(toolReq, data.toUtf8());

	if(d->translate)
		data = KVTranslator::instance()->translateJson(data).toUtf8();

	d->content = data.toUtf8();
	d->offset = 0;
	setHeader(QNetworkRequest::ContentLengthHeader, QVariant(d->content.size()));

	open(ReadOnly | Unbuffered);
	//qDebug() << "translated:" << d->content.constData();

	d->finished = true;

	emit finished();
	emit readChannelFinished();
}

qint64 KVNetworkReply::bytesAvailable() const {
	return d->content.size() - d->offset + QIODevice::bytesAvailable();
}

qint64 KVNetworkReply::readData(char *data, qint64 maxSize) {
	if (d->offset >= d->content.size())
		return -1;

	qint64 numBytes = qMin(maxSize, d->content.size() - d->offset);
	memcpy(data, d->content.constData() + d->offset, numBytes);
	d->offset += numBytes;

	return numBytes;
}

/*
 * Pass all these through to the underlying 'copied' QNetworkRequest because
 * There isn't a copy constructor. I now understand why everything in the
 * standard libraries has a copy constructor...
 */
void KVNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) {
	d->copied->ignoreSslErrors(errors);
}

QNetworkAccessManager* KVNetworkReply::manager() const {
	return d->copied->manager();
}

void KVNetworkReply::setSslConfiguration(const QSslConfiguration &config) {
	d->copied->setSslConfiguration(config);
}

QSslConfiguration KVNetworkReply::sslConfiguration() const {
	return d->copied->sslConfiguration();
}

bool KVNetworkReply::event(QEvent *e) {
	return d->copied->event(e);
}

void KVNetworkReply::abort() {
	d->finished = true; d->copied->abort();
}

void KVNetworkReply::ignoreSslErrors() {
	d->copied->ignoreSslErrors();
}

bool KVNetworkReply::isSequential() const {
	return true;
}
<|endoftext|>


<commit_before>#include <UtH/Engine/TMX/Object.hpp>

#include <tinyxml2.h>

#include <cstdlib>
#include <sstream>

using namespace uth;
using namespace TMX;

Object::Object(tinyxml2::XMLElement* objectElement)
{
    parseObject(objectElement);
}

Object::~Object()
{ }

// Public

const pmath::Rect& Object::GetRectangle() const
{
	return m_rectangle;
}

const std::vector<pmath::Vec2>& Object::GetPoints() const
{
	return m_points;
}

const pmath::Vec2 Object::GetPosition() const
{
	return pmath::Vec2(m_rectangle.position.x, m_rectangle.position.y);
}

std::string Object::GetProperty(const std::string& name) const
{
	auto prop = m_properties.find(name);
	if(prop != m_properties.end())
		return prop->second;

	return std::string();
}

const std::string& Object::GetName() const
{
	return m_name;
}

const std::string& Object::GetType() const
{
	return m_typeString;
}

// Private

void Object::parseObject(tinyxml2::XMLElement* element)
{
    // Parse properties
	m_name = element->Attribute("name");
	m_typeString = element->Attribute("type");

    auto properties = element->FirstChildElement("properties");
    if(properties != 0)
    {
        parseProperties(properties);
    }

    // Parse actual object
	m_rectangle.position.x = element->FloatAttribute("x");
	m_rectangle.position.y = element->FloatAttribute("y");

	// There are only 3 possibilities here but use else if for future compability
	if(element->UnsignedAttribute("width") != 0)
	{
		// Rectangle
		m_type = RECTANGLE;
		m_rectangle.size.x = element->FloatAttribute("width");
		m_rectangle.size.y = element->FloatAttribute("height");

		m_points.push_back(pmath::Vec2(m_rectangle.position.x, m_rectangle.position.y));
		m_points.push_back(pmath::Vec2(m_rectangle.position.x, m_rectangle.position.y-m_rectangle.size.y));
		m_points.push_back(pmath::Vec2(m_rectangle.position.x+m_rectangle.size.x, m_rectangle.position.y-m_rectangle.size.y));
		m_points.push_back(pmath::Vec2(m_rectangle.position.x+m_rectangle.size.x, m_rectangle.position.y));
	}
	else if(element->FirstChildElement("polygon") != 0)
	{
		// Polygon
		m_type = POLYGON;
		std::string points = element->FirstChildElement("polygon")->Attribute("points");
		parsePoints(points);
	}
	else if(element->FirstChildElement("polyline") != 0)
	{
		// Line
		m_type = LINE;
		std::string points = element->FirstChildElement("polyline")->Attribute("points");
		parsePoints(points);
	}
}

void Object::parseProperties(tinyxml2::XMLElement* element)
{
    auto p = element->FirstChildElement("property");
	while(p != 0)
	{
		std::pair<std::string, std::string> tmp;
		tmp.first = p->Attribute("name");
		tmp.second = p->Attribute("value");

		m_properties.insert(tmp);

		p = p->NextSiblingElement("property");
	}
}

void Object::parsePoints(const std::string& points)
{
	std::istringstream pointStream(points);
	std::string point;

	while(std::getline(pointStream, point, ' '))
	{
		std::istringstream componentStream(point);
		std::string x;
		std::string y;
		std::getline(componentStream, x, ',');
		std::getline(componentStream, y);
		// Looks good, right?
		m_points.push_back(pmath::Vec2(
			static_cast<float>(atoi(x.c_str())),
			static_cast<float>(atoi(y.c_str()))
			));
	}

	// Calculate AABB
	float left = 0;
	float right = 0;
	float top = 0;
	float bottom = 0;
	for(auto it = m_points.begin(); it != m_points.end(); ++it)
	{
		auto point = (*it);
		if(point.x < left)
			left = point.x;
		else if(point.x > right)
			right = point.x;

		if(point.y < bottom)
			bottom = point.y;
		else if(point.y > top)
			top = point.y;
	}

	m_rectangle.position.x += left;
	m_rectangle.position.y += bottom;
	m_rectangle.size.x = right - left;
	m_rectangle.size.y = top - bottom;
}
<commit_msg>Fixed Tiled map loading with maps with objects without names or types<commit_after>#include <UtH/Engine/TMX/Object.hpp>

#include <tinyxml2.h>

#include <cstdlib>
#include <sstream>

using namespace uth;
using namespace TMX;

Object::Object(tinyxml2::XMLElement* objectElement)
{
    parseObject(objectElement);
}

Object::~Object()
{ }

// Public

const pmath::Rect& Object::GetRectangle() const
{
	return m_rectangle;
}

const std::vector<pmath::Vec2>& Object::GetPoints() const
{
	return m_points;
}

const pmath::Vec2 Object::GetPosition() const
{
	return pmath::Vec2(m_rectangle.position.x, m_rectangle.position.y);
}

std::string Object::GetProperty(const std::string& name) const
{
	auto prop = m_properties.find(name);
	if(prop != m_properties.end())
		return prop->second;

	return std::string();
}

const std::string& Object::GetName() const
{
	return m_name;
}

const std::string& Object::GetType() const
{
	return m_typeString;
}

// Private

void Object::parseObject(tinyxml2::XMLElement* element)
{
    // Parse properties
	const char* name = element->Attribute("name");
	if (name)
		m_name = name;
	const char* type = element->Attribute("type");
	if (type)
		m_typeString = type;

    auto properties = element->FirstChildElement("properties");
    if(properties != 0)
    {
        parseProperties(properties);
    }

    // Parse actual object
	m_rectangle.position.x = element->FloatAttribute("x");
	m_rectangle.position.y = element->FloatAttribute("y");

	// There are only 3 possibilities here but use else if for future compability
	if(element->UnsignedAttribute("width") != 0)
	{
		// Rectangle
		m_type = RECTANGLE;
		m_rectangle.size.x = element->FloatAttribute("width");
		m_rectangle.size.y = element->FloatAttribute("height");

		m_points.push_back(pmath::Vec2(m_rectangle.position.x, m_rectangle.position.y));
		m_points.push_back(pmath::Vec2(m_rectangle.position.x, m_rectangle.position.y-m_rectangle.size.y));
		m_points.push_back(pmath::Vec2(m_rectangle.position.x+m_rectangle.size.x, m_rectangle.position.y-m_rectangle.size.y));
		m_points.push_back(pmath::Vec2(m_rectangle.position.x+m_rectangle.size.x, m_rectangle.position.y));
	}
	else if(element->FirstChildElement("polygon") != 0)
	{
		// Polygon
		m_type = POLYGON;
		std::string points = element->FirstChildElement("polygon")->Attribute("points");
		parsePoints(points);
	}
	else if(element->FirstChildElement("polyline") != 0)
	{
		// Line
		m_type = LINE;
		std::string points = element->FirstChildElement("polyline")->Attribute("points");
		parsePoints(points);
	}
}

void Object::parseProperties(tinyxml2::XMLElement* element)
{
    auto p = element->FirstChildElement("property");
	while(p != 0)
	{
		std::pair<std::string, std::string> tmp;
		tmp.first = p->Attribute("name");
		tmp.second = p->Attribute("value");

		m_properties.insert(tmp);

		p = p->NextSiblingElement("property");
	}
}

void Object::parsePoints(const std::string& points)
{
	std::istringstream pointStream(points);
	std::string point;

	while(std::getline(pointStream, point, ' '))
	{
		std::istringstream componentStream(point);
		std::string x;
		std::string y;
		std::getline(componentStream, x, ',');
		std::getline(componentStream, y);
		// Looks good, right?
		m_points.push_back(pmath::Vec2(
			static_cast<float>(atoi(x.c_str())),
			static_cast<float>(atoi(y.c_str()))
			));
	}

	// Calculate AABB
	float left = 0;
	float right = 0;
	float top = 0;
	float bottom = 0;
	for(auto it = m_points.begin(); it != m_points.end(); ++it)
	{
		auto point = (*it);
		if(point.x < left)
			left = point.x;
		else if(point.x > right)
			right = point.x;

		if(point.y < bottom)
			bottom = point.y;
		else if(point.y > top)
			top = point.y;
	}

	m_rectangle.position.x += left;
	m_rectangle.position.y += bottom;
	m_rectangle.size.x = right - left;
	m_rectangle.size.y = top - bottom;
}
<|endoftext|>


<commit_before>#include "ros/ros.h"
#include "sensor_msgs/Joy.h"
#include "geometry_msgs/Accel.h"

#undef zero

class Accel
{
  private:
    ros::NodeHandle nh;
    ros::Publisher accels;
    ros::Subscriber js;
    geometry_msgs::Accel accel;

  public:
    Accel();
    void joy_callback(const sensor_msgs::Joy::ConstPtr& joy);
    void loop();
};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "joy_accel");
  Accel accel;
  accel.loop();
}

Accel::Accel()
{
  js = nh.subscribe<sensor_msgs::Joy>("joy", 1, &Accel::joy_callback, this);
  accels = nh.advertise<geometry_msgs::Accel>("command/accel", 1);
}

void Accel::joy_callback(const sensor_msgs::Joy::ConstPtr& joy)
{
#ifdef zero
  accel.linear.x = 0;
  accel.linear.y = 0;
  accel.linear.z = 0;

  accel.angular.x = 0;
  accel.angular.y = 0;
  accel.angular.z = 0;
#else
  accel.linear.x = joy->axes[1];
  accel.linear.y = joy->axes[0];
  accel.linear.z = (joy->axes[14] - joy->axes[15]);

  accel.angular.x = 3.14159 * joy->axes[2] * -1;
  accel.angular.y = 3.14159 * joy->axes[3];
  accel.angular.z = 3.14159 * (joy->axes[13] - joy->axes[12]);
#endif
  // accel.linear.x = 5 * joy->axes[1];
  // accel.linear.y = 0;
  // accel.linear.z = 5 * (joy->axes[14] - joy->axes[15]);
  //
  // accel.angular.x = 5 * 2 * 3.14159 * joy->axes[2] * -1;
  // accel.angular.y = 5 * 2 * 3.14159 * joy->axes[3];
  // accel.angular.z = 5 * 2 * 3.14159 * (joy->axes[13] - joy->axes[12]);

  accels.publish(accel);
}

void Accel::loop()
{
  ros::Rate rate(30);
  while(ros::ok())
  {
    ros::spinOnce();
    rate.sleep();
  }
}
<commit_msg>Make teleop accelerations reasonable.<commit_after>#include "ros/ros.h"
#include "sensor_msgs/Joy.h"
#include "geometry_msgs/Accel.h"

#undef zero

class Accel
{
  private:
    ros::NodeHandle nh;
    ros::Publisher accels;
    ros::Subscriber js;
    geometry_msgs::Accel accel;

  public:
    Accel();
    void joy_callback(const sensor_msgs::Joy::ConstPtr& joy);
    void loop();
};

int main(int argc, char **argv)
{
  ros::init(argc, argv, "joy_accel");
  Accel accel;
  accel.loop();
}

Accel::Accel()
{
  js = nh.subscribe<sensor_msgs::Joy>("joy", 1, &Accel::joy_callback, this);
  accels = nh.advertise<geometry_msgs::Accel>("command/accel", 1);
}

void Accel::joy_callback(const sensor_msgs::Joy::ConstPtr& joy)
{
#ifdef zero
  accel.linear.x = 0;
  accel.linear.y = 0;
  accel.linear.z = 0;

  accel.angular.x = 0;
  accel.angular.y = 0;
  accel.angular.z = 0;
#else
  accel.linear.x = joy->axes[1];
  accel.linear.y = joy->axes[0];
  accel.linear.z = (joy->axes[14] - joy->axes[15]);

  accel.angular.x = 3.14159 * joy->axes[2] * -1;
  accel.angular.y = 3.14159 * joy->axes[3];
  accel.angular.z = 3.14159 * (joy->axes[13] - joy->axes[12]);
#endif
  // accel.linear.x = 5 * joy->axes[1];
  // accel.linear.y = 0;
  // accel.linear.z = 5 * (joy->axes[14] - joy->axes[15]);
  //
  // accel.angular.x = 5 * 2 * 3.14159 * joy->axes[2] * -1;
  // accel.angular.y = 5 * 2 * 3.14159 * joy->axes[3];
  // accel.angular.z = 5 * 2 * 3.14159 * (joy->axes[13] - joy->axes[12]);

  accels.publish(accel);
}

void Accel::loop()
{
  ros::Rate rate(10);
  while(ros::ok())
  {
    ros::spinOnce();
    rate.sleep();
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/events/event.h"

#include <gdk/gdk.h>

#include "base/logging.h"
#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
#include "ui/gfx/point.h"

namespace {

unsigned int GetGdkStateFromNative(GdkEvent* gdk_event) {
  switch (gdk_event->type) {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      return gdk_event->key.state;
    case GDK_BUTTON_PRESS:
    case GDK_2BUTTON_PRESS:
    case GDK_3BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      return gdk_event->button.state;
    case GDK_SCROLL:
      return gdk_event->scroll.state;
    case GDK_MOTION_NOTIFY:
      return gdk_event->motion.state;
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      return gdk_event->crossing.state;
    default:
      NOTREACHED();
      break;
  }
  return 0;
}

int GetFlagsFromGdkState(unsigned int state) {
  int flags = 0;
  flags |= (state & GDK_LOCK_MASK) ? ui::EF_CAPS_LOCK_DOWN : 0;
  flags |= (state & GDK_CONTROL_MASK) ? ui::EF_CONTROL_DOWN : 0;
  flags |= (state & GDK_SHIFT_MASK) ? ui::EF_SHIFT_DOWN : 0;
  flags |= (state & GDK_MOD1_MASK) ? ui::EF_ALT_DOWN : 0;
  flags |= (state & GDK_BUTTON1_MASK) ? ui::EF_LEFT_BUTTON_DOWN : 0;
  flags |= (state & GDK_BUTTON2_MASK) ? ui::EF_MIDDLE_BUTTON_DOWN : 0;
  flags |= (state & GDK_BUTTON3_MASK) ? ui::EF_RIGHT_BUTTON_DOWN : 0;
  return flags;
}

////////////////////////////////////////////////////////////////////////////////
// These functions mirror ui/base/events.h, but GTK is in the midst of removal.

ui::EventType EventTypeFromNative(GdkEvent* gdk_event) {
  // Add new event types as necessary.
  switch (gdk_event->type) {
    case GDK_2BUTTON_PRESS:
    case GDK_3BUTTON_PRESS:
    case GDK_BUTTON_PRESS:
      return ui::ET_MOUSE_PRESSED;
    case GDK_BUTTON_RELEASE:
      return ui::ET_MOUSE_RELEASED;
    case GDK_DRAG_MOTION:
      return ui::ET_MOUSE_DRAGGED;
    case GDK_ENTER_NOTIFY:
      return ui::ET_MOUSE_ENTERED;
    case GDK_KEY_PRESS:
      return ui::ET_KEY_PRESSED;
    case GDK_KEY_RELEASE:
      return ui::ET_KEY_RELEASED;
    case GDK_LEAVE_NOTIFY:
      return ui::ET_MOUSE_EXITED;
    case GDK_MOTION_NOTIFY:
      if (gdk_event->motion.state & GDK_BUTTON1_MASK ||
          gdk_event->motion.state & GDK_BUTTON2_MASK ||
          gdk_event->motion.state & GDK_BUTTON3_MASK ||
          gdk_event->motion.state & GDK_BUTTON4_MASK ||
          gdk_event->motion.state & GDK_BUTTON5_MASK) {
        return ui::ET_MOUSE_DRAGGED;
      }
      return ui::ET_MOUSE_MOVED;
    case GDK_SCROLL:
      return ui::ET_MOUSEWHEEL;
    default:
      NOTREACHED();
      break;
  }
  return ui::ET_UNKNOWN;
}

int EventFlagsFromNative(GdkEvent* gdk_event) {
  int flags = GetFlagsFromGdkState(GetGdkStateFromNative(gdk_event));
  if (gdk_event->type == GDK_2BUTTON_PRESS)
    flags |= ui::EF_IS_DOUBLE_CLICK;
  if (gdk_event->type == GDK_BUTTON_PRESS ||
      gdk_event->type == GDK_2BUTTON_PRESS ||
      gdk_event->type == GDK_3BUTTON_PRESS ||
      gdk_event->type == GDK_BUTTON_RELEASE) {
    switch (gdk_event->button.button) {
      case 1:
        return flags | ui::EF_LEFT_BUTTON_DOWN;
      case 2:
        return flags | ui::EF_MIDDLE_BUTTON_DOWN;
      case 3:
        return flags | ui::EF_RIGHT_BUTTON_DOWN;
    }
  }
  return flags;
}

gfx::Point EventLocationFromNative(GdkEvent* gdk_event) {
  double x = 0, y = 0;
  if (gdk_event_get_coords(gdk_event, &x, &y))
    return gfx::Point(static_cast<int>(x), static_cast<int>(y));
  return gfx::Point();
}

ui::KeyboardCode KeyboardCodeFromNative(GdkEvent* gdk_event) {
  DCHECK(gdk_event->type == GDK_KEY_PRESS ||
         gdk_event->type == GDK_KEY_RELEASE);
  return ui::KeyboardCodeFromGdkEventKey(&gdk_event->key);
}

bool IsMouseEvent(GdkEvent* gdk_event) {
  return gdk_event->type == GDK_MOTION_NOTIFY ||
         gdk_event->type == GDK_BUTTON_PRESS ||
         gdk_event->type == GDK_2BUTTON_PRESS ||
         gdk_event->type == GDK_3BUTTON_PRESS ||
         gdk_event->type == GDK_BUTTON_RELEASE;
}

int GetMouseWheelOffset(GdkEvent* gdk_event) {
  DCHECK(gdk_event->type == GDK_SCROLL);
  int offset = (gdk_event->scroll.direction == GDK_SCROLL_UP ||
                gdk_event->scroll.direction == GDK_SCROLL_LEFT) ? 1 : -1;
  return offset;
}

}  // namespace

namespace views {

////////////////////////////////////////////////////////////////////////////////
// Event, protected:

Event::Event(GdkEvent* gdk_event, ui::EventType type, int flags)
    : native_event_(NULL),
      gdk_event_(gdk_event),
      type_(type),
      time_stamp_(base::Time::NowFromSystemTime()),
      flags_(flags) {
}

////////////////////////////////////////////////////////////////////////////////
// LocatedEvent, protected:

LocatedEvent::LocatedEvent(GdkEvent* gdk_event)
    : Event(gdk_event,
            EventTypeFromNative(gdk_event),
            EventFlagsFromNative(gdk_event)),
      location_(EventLocationFromNative(gdk_event)) {
}

////////////////////////////////////////////////////////////////////////////////
// KeyEvent, public:

KeyEvent::KeyEvent(GdkEvent* gdk_event)
    : Event(gdk_event,
            EventTypeFromNative(gdk_event),
            EventFlagsFromNative(gdk_event)),
      key_code_(KeyboardCodeFromNative(gdk_event)),
      character_(0),
      unmodified_character_(0) {
}

////////////////////////////////////////////////////////////////////////////////
// MouseEvent, public:

MouseEvent::MouseEvent(GdkEvent* gdk_event)
    : LocatedEvent(gdk_event) {
}

////////////////////////////////////////////////////////////////////////////////
// MouseWheelEvent, public:

MouseWheelEvent::MouseWheelEvent(GdkEvent* gdk_event)
    : MouseEvent(gdk_event),
      offset_(kWheelDelta * GetMouseWheelOffset(gdk_event)) {
}

}  // namespace views
<commit_msg>views: Remove unused/deprecated IsMouseEvent() function.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "views/events/event.h"

#include <gdk/gdk.h>

#include "base/logging.h"
#include "ui/base/keycodes/keyboard_code_conversion_gtk.h"
#include "ui/gfx/point.h"

namespace {

unsigned int GetGdkStateFromNative(GdkEvent* gdk_event) {
  switch (gdk_event->type) {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      return gdk_event->key.state;
    case GDK_BUTTON_PRESS:
    case GDK_2BUTTON_PRESS:
    case GDK_3BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      return gdk_event->button.state;
    case GDK_SCROLL:
      return gdk_event->scroll.state;
    case GDK_MOTION_NOTIFY:
      return gdk_event->motion.state;
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      return gdk_event->crossing.state;
    default:
      NOTREACHED();
      break;
  }
  return 0;
}

int GetFlagsFromGdkState(unsigned int state) {
  int flags = 0;
  flags |= (state & GDK_LOCK_MASK) ? ui::EF_CAPS_LOCK_DOWN : 0;
  flags |= (state & GDK_CONTROL_MASK) ? ui::EF_CONTROL_DOWN : 0;
  flags |= (state & GDK_SHIFT_MASK) ? ui::EF_SHIFT_DOWN : 0;
  flags |= (state & GDK_MOD1_MASK) ? ui::EF_ALT_DOWN : 0;
  flags |= (state & GDK_BUTTON1_MASK) ? ui::EF_LEFT_BUTTON_DOWN : 0;
  flags |= (state & GDK_BUTTON2_MASK) ? ui::EF_MIDDLE_BUTTON_DOWN : 0;
  flags |= (state & GDK_BUTTON3_MASK) ? ui::EF_RIGHT_BUTTON_DOWN : 0;
  return flags;
}

////////////////////////////////////////////////////////////////////////////////
// These functions mirror ui/base/events.h, but GTK is in the midst of removal.

ui::EventType EventTypeFromNative(GdkEvent* gdk_event) {
  // Add new event types as necessary.
  switch (gdk_event->type) {
    case GDK_2BUTTON_PRESS:
    case GDK_3BUTTON_PRESS:
    case GDK_BUTTON_PRESS:
      return ui::ET_MOUSE_PRESSED;
    case GDK_BUTTON_RELEASE:
      return ui::ET_MOUSE_RELEASED;
    case GDK_DRAG_MOTION:
      return ui::ET_MOUSE_DRAGGED;
    case GDK_ENTER_NOTIFY:
      return ui::ET_MOUSE_ENTERED;
    case GDK_KEY_PRESS:
      return ui::ET_KEY_PRESSED;
    case GDK_KEY_RELEASE:
      return ui::ET_KEY_RELEASED;
    case GDK_LEAVE_NOTIFY:
      return ui::ET_MOUSE_EXITED;
    case GDK_MOTION_NOTIFY:
      if (gdk_event->motion.state & GDK_BUTTON1_MASK ||
          gdk_event->motion.state & GDK_BUTTON2_MASK ||
          gdk_event->motion.state & GDK_BUTTON3_MASK ||
          gdk_event->motion.state & GDK_BUTTON4_MASK ||
          gdk_event->motion.state & GDK_BUTTON5_MASK) {
        return ui::ET_MOUSE_DRAGGED;
      }
      return ui::ET_MOUSE_MOVED;
    case GDK_SCROLL:
      return ui::ET_MOUSEWHEEL;
    default:
      NOTREACHED();
      break;
  }
  return ui::ET_UNKNOWN;
}

int EventFlagsFromNative(GdkEvent* gdk_event) {
  int flags = GetFlagsFromGdkState(GetGdkStateFromNative(gdk_event));
  if (gdk_event->type == GDK_2BUTTON_PRESS)
    flags |= ui::EF_IS_DOUBLE_CLICK;
  if (gdk_event->type == GDK_BUTTON_PRESS ||
      gdk_event->type == GDK_2BUTTON_PRESS ||
      gdk_event->type == GDK_3BUTTON_PRESS ||
      gdk_event->type == GDK_BUTTON_RELEASE) {
    switch (gdk_event->button.button) {
      case 1:
        return flags | ui::EF_LEFT_BUTTON_DOWN;
      case 2:
        return flags | ui::EF_MIDDLE_BUTTON_DOWN;
      case 3:
        return flags | ui::EF_RIGHT_BUTTON_DOWN;
    }
  }
  return flags;
}

gfx::Point EventLocationFromNative(GdkEvent* gdk_event) {
  double x = 0, y = 0;
  if (gdk_event_get_coords(gdk_event, &x, &y))
    return gfx::Point(static_cast<int>(x), static_cast<int>(y));
  return gfx::Point();
}

ui::KeyboardCode KeyboardCodeFromNative(GdkEvent* gdk_event) {
  DCHECK(gdk_event->type == GDK_KEY_PRESS ||
         gdk_event->type == GDK_KEY_RELEASE);
  return ui::KeyboardCodeFromGdkEventKey(&gdk_event->key);
}

int GetMouseWheelOffset(GdkEvent* gdk_event) {
  DCHECK(gdk_event->type == GDK_SCROLL);
  int offset = (gdk_event->scroll.direction == GDK_SCROLL_UP ||
                gdk_event->scroll.direction == GDK_SCROLL_LEFT) ? 1 : -1;
  return offset;
}

}  // namespace

namespace views {

////////////////////////////////////////////////////////////////////////////////
// Event, protected:

Event::Event(GdkEvent* gdk_event, ui::EventType type, int flags)
    : native_event_(NULL),
      gdk_event_(gdk_event),
      type_(type),
      time_stamp_(base::Time::NowFromSystemTime()),
      flags_(flags) {
}

////////////////////////////////////////////////////////////////////////////////
// LocatedEvent, protected:

LocatedEvent::LocatedEvent(GdkEvent* gdk_event)
    : Event(gdk_event,
            EventTypeFromNative(gdk_event),
            EventFlagsFromNative(gdk_event)),
      location_(EventLocationFromNative(gdk_event)) {
}

////////////////////////////////////////////////////////////////////////////////
// KeyEvent, public:

KeyEvent::KeyEvent(GdkEvent* gdk_event)
    : Event(gdk_event,
            EventTypeFromNative(gdk_event),
            EventFlagsFromNative(gdk_event)),
      key_code_(KeyboardCodeFromNative(gdk_event)),
      character_(0),
      unmodified_character_(0) {
}

////////////////////////////////////////////////////////////////////////////////
// MouseEvent, public:

MouseEvent::MouseEvent(GdkEvent* gdk_event)
    : LocatedEvent(gdk_event) {
}

////////////////////////////////////////////////////////////////////////////////
// MouseWheelEvent, public:

MouseWheelEvent::MouseWheelEvent(GdkEvent* gdk_event)
    : MouseEvent(gdk_event),
      offset_(kWheelDelta * GetMouseWheelOffset(gdk_event)) {
}

}  // namespace views
<|endoftext|>


<commit_before>/***********************************************************************
    filename:   TabControlDemo.cpp
    created:    27/6/2006
    author:     Andrew Zabolotny
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "SampleBase.h"
#include "CEGUI/CEGUI.h"

using namespace CEGUI;

#define SKIN "TaharezLook"
// for this to work you'll have to change the .layout files
//#define SKIN "WindowsLook"

static const char* PageText [] =
{
    "This is page three",
    "And this is page four, it's not too different from page three, isn't it?",
    "Yep, you guessed, this is page five",
    "And this is page six",
    "Seven",
    "Eight",
    "Nine. Quite boring, isn't it?",
    "Ten",
    "Eleven",
    "Twelve",
    "Thirteen",
    "Fourteen",
    "Fifteen",
    "And, finally, sixteen. Congrats, you found the last page!",
};

// Sample sub-class for ListboxTextItem that auto-sets the selection brush
// image.  This saves doing it manually every time in the code.
class MyListItem : public ListboxTextItem
{
public:
    MyListItem(const String& text) : ListboxTextItem(text)
    {
        setSelectionBrushImage(SKIN "/MultiListSelectionBrush");
    }
};

// Sample class
class TabControlDemo : public Sample
{
public:
    // method to initialse the samples windows and events.
    bool initialise(CEGUI::GUIContext* guiContext)
    {
        d_guiContext = guiContext;
        d_usedFiles = CEGUI::String(__FILE__);

        // load font and setup default if not loaded via scheme
        Font& defaultFont = FontManager::getSingleton().createFromFile("DejaVuSans-12.font");
        // Set default font for the gui context
        guiContext->setDefaultFont(&defaultFont);

        // we will use of the WindowManager.
        WindowManager& winMgr = WindowManager::getSingleton();

        // load scheme and set up defaults
        SchemeManager::getSingleton().createFromFile(SKIN ".scheme");
        d_guiContext->getMouseCursor().setDefaultImage(SKIN "/MouseArrow");

        // load an image to use as a background
        if( !ImageManager::getSingleton().isDefined("SpaceBackgroundImage") )
            ImageManager::getSingleton().addFromImageFile("SpaceBackgroundImage", "SpaceBackground.jpg");

        // here we will use a StaticImage as the root, then we can use it to place a background image
        Window* background = winMgr.createWindow(SKIN "/StaticImage");
        // set area rectangle
        background->setArea(URect(cegui_reldim(0), cegui_reldim(0),
                                  cegui_reldim(1), cegui_reldim(1)));
        // disable frame and standard background
        background->setProperty("FrameEnabled", "false");
        background->setProperty("BackgroundEnabled", "false");
        // set the background image
        background->setProperty("Image", "SpaceBackgroundImage");
        // install this as the root GUI sheet
        d_guiContext->setRootWindow(background);

        // set tooltip styles (by default there is none)
        d_guiContext->setDefaultTooltipType(SKIN "/Tooltip");

        // load some demo windows and attach to the background 'root'
        background->addChild(winMgr.loadLayoutFromFile("TabControlDemo.layout"));

        TabControl* tc = static_cast<TabControl*>(background->getChild("Frame/TabControl"));

        // Add some pages to tab control
        tc->addTab(winMgr.loadLayoutFromFile("TabPage1.layout"));
        tc->addTab(winMgr.loadLayoutFromFile("TabPage2.layout"));

        WindowManager::getSingleton().DEBUG_dumpWindowNames("asd");

        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/AddTab"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleAddTab, this));

        // Click to visit this tab
        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/Go"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleGoto, this));

        // Click to make this tab button visible (when scrolling is required)
        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/Show"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleShow, this));

        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/Del"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleDel, this));

        RadioButton* rb = static_cast<RadioButton*>(
                              background->getChild("Frame/TabControl/Page1/TabPaneTop"));
        rb->setSelected(tc->getTabPanePosition() == TabControl::Top);
        rb->subscribeEvent(
            RadioButton::EventSelectStateChanged,
            Event::Subscriber(&TabControlDemo::handleTabPanePos, this));

        rb = static_cast<RadioButton*>(
                 background->getChild("Frame/TabControl/Page1/TabPaneBottom"));
        rb->setSelected(tc->getTabPanePosition() == TabControl::Bottom);
        rb->subscribeEvent(
            RadioButton::EventSelectStateChanged,
            Event::Subscriber(&TabControlDemo::handleTabPanePos, this));

        Scrollbar* sb = static_cast<Scrollbar*>(
                            background->getChild("Frame/TabControl/Page1/TabHeight"));
        sb->setScrollPosition(tc->getTabHeight().d_offset);
        sb->subscribeEvent(
            Scrollbar::EventScrollPositionChanged,
            Event::Subscriber(&TabControlDemo::handleTabHeight, this));

        sb = static_cast<Scrollbar*>(
                 background->getChild("Frame/TabControl/Page1/TabPadding"));
        sb->setScrollPosition(tc->getTabTextPadding().d_offset);
        sb->subscribeEvent(
            Scrollbar::EventScrollPositionChanged,
            Event::Subscriber(&TabControlDemo::handleTabPadding, this));

        refreshPageList();

        // From now on, we don't rely on the exceptions anymore, but perform nice (and recommended) checks
        // ourselves.

        return true;
    }

    // method to perform any required cleanup operations.
    void deinitialise()
    {
    }

    void refreshPageList()
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            lbox->resetList();

            for (size_t i = 0; i < tc->getTabCount(); i++)
            {
                lbox->addItem(new MyListItem(
                                  tc->getTabContentsAtIndex(i)->getName()));
            }
        }
    }

    bool handleTabPanePos(const EventArgs& e)
    {
        TabControl::TabPanePosition tpp;

        switch (static_cast<const WindowEventArgs&>(e).window->getID())
        {
        case 0:
            tpp = TabControl::Top;
            break;
        case 1:
            tpp = TabControl::Bottom;
            break;
        default:
            return false;
        }

        // Check if the window exists
        Window* root = d_guiContext->getRootWindow();

        if (root->isChild("Frame/TabControl"))
        {
            static_cast<TabControl*>(root->getChild(
                                         "Frame/TabControl"))->setTabPanePosition(tpp);
        }

        return true;
    }

    bool handleTabHeight(const EventArgs& e)
    {
        Scrollbar* sb = static_cast<Scrollbar*>(
                            static_cast<const WindowEventArgs&>(e).window);

        // Check if the window exists
        Window* root = d_guiContext->getRootWindow();

        if (root->isChild("Frame/TabControl"))
        {
            static_cast<TabControl*>(root->getChild(
                                         "Frame/TabControl"))->setTabHeight(
                                             UDim(0, sb->getScrollPosition()));
        }

        // The return value mainly sais that we handled it, not if something failed.
        return true;
    }

    bool handleTabPadding(const EventArgs& e)
    {
        Scrollbar* sb = static_cast<Scrollbar*>(
                            static_cast<const WindowEventArgs&>(e).window);

        // Check if the window exists
        Window* root = d_guiContext->getRootWindow();

        if (root->isChild("Frame/TabControl"))
        {
            static_cast<TabControl*>(root->getChild(
                                         "Frame/TabControl"))->setTabTextPadding(
                                             UDim(0, sb->getScrollPosition()));
        }

        return true;
    }

    bool handleAddTab(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();

        // Check if the window exists
        if (root->isChild("Frame/TabControl"))
        {
            TabControl* tc = static_cast<TabControl*>(root->getChild(
                                 "Frame/TabControl"));

            // Add some tab buttons once
            for (int num = 3; num <= 16; num++)
            {
                std::stringstream pgname;
                pgname << "Page" << num;

                if (root->isChild(String("Frame/TabControl/") + pgname.str().c_str()))
                    // Next
                    continue;

                Window* pg = 0;

                pg = WindowManager::getSingleton().loadLayoutFromFile("TabPage.layout");
                CEGUI_TRY
                {
                    pg = WindowManager::getSingleton().loadLayoutFromFile("TabPage.layout");
                    pg->setName(String(pgname.str().c_str()));
                }
                CEGUI_CATCH(CEGUI::Exception&)
                {
                    outputExceptionMessage("Some error occured while adding a tabpage. Please see the logfile.");
                    break;
                }

                // This window has just been created while loading the layout
                if (pg->isChild("Text"))
                {
                    Window* txt = pg->getChild("Text");
                    txt->setText(PageText [num - 3]);

                    pg->setText(pgname.str().c_str());
                    tc->addTab(pg);

                    refreshPageList();
                    break;
                }
            }
        }

        return true;
    }

    bool handleGoto(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            ListboxItem* lbi = lbox->getFirstSelectedItem();

            if (lbi)
            {
                tc->setSelectedTab(lbi->getText());
            }
        }

        return true;
    }

    bool handleShow(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            ListboxItem* lbi = lbox->getFirstSelectedItem();

            if (lbi)
            {
                tc->makeTabVisible(lbi->getText());
            }
        }

        return true;
    }

    bool handleDel(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            ListboxItem* lbi = lbox->getFirstSelectedItem();

            if (lbi)
            {
                Window* content = tc->getTabContents(lbi->getText());
                tc->removeTab(lbi->getText());
                // Remove the actual window from Cegui
                WindowManager::getSingleton().destroyWindow(content);

                refreshPageList();
            }
        }

        return true;
    }

    protected:
        CEGUI::GUIContext* d_guiContext;
};

/*************************************************************************
    Define the module function that returns an instance of the sample
*************************************************************************/
extern "C" SAMPLE_EXPORT Sample& getSampleInstance()
{
    static TabControlDemo sample;
    return sample;
}
<commit_msg>FIX: After-Merge fix<commit_after>/***********************************************************************
    filename:   TabControlDemo.cpp
    created:    27/6/2006
    author:     Andrew Zabolotny
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2006 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/
#include "SampleBase.h"
#include "CEGUI/CEGUI.h"

using namespace CEGUI;

#define SKIN "TaharezLook"
// for this to work you'll have to change the .layout files
//#define SKIN "WindowsLook"

static const char* PageText [] =
{
    "This is page three",
    "And this is page four, it's not too different from page three, isn't it?",
    "Yep, you guessed, this is page five",
    "And this is page six",
    "Seven",
    "Eight",
    "Nine. Quite boring, isn't it?",
    "Ten",
    "Eleven",
    "Twelve",
    "Thirteen",
    "Fourteen",
    "Fifteen",
    "And, finally, sixteen. Congrats, you found the last page!",
};

// Sample sub-class for ListboxTextItem that auto-sets the selection brush
// image.  This saves doing it manually every time in the code.
class MyListItem : public ListboxTextItem
{
public:
    MyListItem(const String& text) : ListboxTextItem(text)
    {
        setSelectionBrushImage(SKIN "/MultiListSelectionBrush");
    }
};

// Sample class
class TabControlDemo : public Sample
{
public:
    // method to initialse the samples windows and events.
    bool initialise(CEGUI::GUIContext* guiContext)
    {
        d_guiContext = guiContext;
        d_usedFiles = CEGUI::String(__FILE__);

        // load font and setup default if not loaded via scheme
        Font& defaultFont = FontManager::getSingleton().createFromFile("DejaVuSans-12.font");
        // Set default font for the gui context
        guiContext->setDefaultFont(&defaultFont);

        // we will use of the WindowManager.
        WindowManager& winMgr = WindowManager::getSingleton();

        // load scheme and set up defaults
        SchemeManager::getSingleton().createFromFile(SKIN ".scheme");
        d_guiContext->getMouseCursor().setDefaultImage(SKIN "/MouseArrow");

        // load an image to use as a background
        if( !ImageManager::getSingleton().isDefined("SpaceBackgroundImage") )
            ImageManager::getSingleton().addFromImageFile("SpaceBackgroundImage", "SpaceBackground.jpg");

        // here we will use a StaticImage as the root, then we can use it to place a background image
        Window* background = winMgr.createWindow(SKIN "/StaticImage");
        // set area rectangle
        background->setArea(URect(cegui_reldim(0), cegui_reldim(0),
                                  cegui_reldim(1), cegui_reldim(1)));
        // disable frame and standard background
        background->setProperty("FrameEnabled", "false");
        background->setProperty("BackgroundEnabled", "false");
        // set the background image
        background->setProperty("Image", "SpaceBackgroundImage");
        // install this as the root GUI sheet
        d_guiContext->setRootWindow(background);

        // set tooltip styles (by default there is none)
        d_guiContext->setDefaultTooltipType(SKIN "/Tooltip");

        // load some demo windows and attach to the background 'root'
        background->addChild(winMgr.loadLayoutFromFile("TabControlDemo.layout"));

        TabControl* tc = static_cast<TabControl*>(background->getChild("Frame/TabControl"));

        // Add some pages to tab control
        tc->addTab(winMgr.loadLayoutFromFile("TabPage1.layout"));
        tc->addTab(winMgr.loadLayoutFromFile("TabPage2.layout"));

        WindowManager::getSingleton().DEBUG_dumpWindowNames("asd");

        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/AddTab"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleAddTab, this));

        // Click to visit this tab
        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/Go"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleGoto, this));

        // Click to make this tab button visible (when scrolling is required)
        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/Show"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleShow, this));

        static_cast<PushButton*>(
            background->getChild("Frame/TabControl/Page1/Del"))->subscribeEvent(
                PushButton::EventClicked,
                Event::Subscriber(&TabControlDemo::handleDel, this));

        RadioButton* rb = static_cast<RadioButton*>(
                              background->getChild("Frame/TabControl/Page1/TabPaneTop"));
        rb->setSelected(tc->getTabPanePosition() == TabControl::Top);
        rb->subscribeEvent(
            RadioButton::EventSelectStateChanged,
            Event::Subscriber(&TabControlDemo::handleTabPanePos, this));

        rb = static_cast<RadioButton*>(
                 background->getChild("Frame/TabControl/Page1/TabPaneBottom"));
        rb->setSelected(tc->getTabPanePosition() == TabControl::Bottom);
        rb->subscribeEvent(
            RadioButton::EventSelectStateChanged,
            Event::Subscriber(&TabControlDemo::handleTabPanePos, this));

        Scrollbar* sb = static_cast<Scrollbar*>(
                            background->getChild("Frame/TabControl/Page1/TabHeight"));
        sb->setScrollPosition(tc->getTabHeight().d_offset);
        sb->subscribeEvent(
            Scrollbar::EventScrollPositionChanged,
            Event::Subscriber(&TabControlDemo::handleTabHeight, this));

        sb = static_cast<Scrollbar*>(
                 background->getChild("Frame/TabControl/Page1/TabPadding"));
        sb->setScrollPosition(tc->getTabTextPadding().d_offset);
        sb->subscribeEvent(
            Scrollbar::EventScrollPositionChanged,
            Event::Subscriber(&TabControlDemo::handleTabPadding, this));

        refreshPageList();

        // From now on, we don't rely on the exceptions anymore, but perform nice (and recommended) checks
        // ourselves.

        return true;
    }

    // method to perform any required cleanup operations.
    void deinitialise()
    {
    }

    void refreshPageList()
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            lbox->resetList();

            for (size_t i = 0; i < tc->getTabCount(); i++)
            {
                lbox->addItem(new MyListItem(
                                  tc->getTabContentsAtIndex(i)->getName()));
            }
        }
    }

    bool handleTabPanePos(const EventArgs& e)
    {
        TabControl::TabPanePosition tpp;

        switch (static_cast<const WindowEventArgs&>(e).window->getID())
        {
        case 0:
            tpp = TabControl::Top;
            break;
        case 1:
            tpp = TabControl::Bottom;
            break;
        default:
            return false;
        }

        // Check if the window exists
        Window* root = d_guiContext->getRootWindow();

        if (root->isChild("Frame/TabControl"))
        {
            static_cast<TabControl*>(root->getChild(
                                         "Frame/TabControl"))->setTabPanePosition(tpp);
        }

        return true;
    }

    bool handleTabHeight(const EventArgs& e)
    {
        Scrollbar* sb = static_cast<Scrollbar*>(
                            static_cast<const WindowEventArgs&>(e).window);

        // Check if the window exists
        Window* root = d_guiContext->getRootWindow();

        if (root->isChild("Frame/TabControl"))
        {
            static_cast<TabControl*>(root->getChild(
                                         "Frame/TabControl"))->setTabHeight(
                                             UDim(0, sb->getScrollPosition()));
        }

        // The return value mainly sais that we handled it, not if something failed.
        return true;
    }

    bool handleTabPadding(const EventArgs& e)
    {
        Scrollbar* sb = static_cast<Scrollbar*>(
                            static_cast<const WindowEventArgs&>(e).window);

        // Check if the window exists
        Window* root = d_guiContext->getRootWindow();

        if (root->isChild("Frame/TabControl"))
        {
            static_cast<TabControl*>(root->getChild(
                                         "Frame/TabControl"))->setTabTextPadding(
                                             UDim(0, sb->getScrollPosition()));
        }

        return true;
    }

    bool handleAddTab(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();

        // Check if the window exists
        if (root->isChild("Frame/TabControl"))
        {
            TabControl* tc = static_cast<TabControl*>(root->getChild(
                                 "Frame/TabControl"));

            // Add some tab buttons once
            for (int num = 3; num <= 16; num++)
            {
                std::stringstream pgname;
                pgname << "Page" << num;

                if (root->isChild(String("Frame/TabControl/") + pgname.str().c_str()))
                    // Next
                    continue;

                Window* pg = 0;

                pg = WindowManager::getSingleton().loadLayoutFromFile("TabPage.layout");
                CEGUI_TRY
                {
                    pg = WindowManager::getSingleton().loadLayoutFromFile("TabPage.layout");
                    pg->setName(String(pgname.str().c_str()));
                }
                CEGUI_CATCH(CEGUI::Exception&)
                {
                    Logger::getSingleton().logEvent("Some error occured while adding a tabpage. Please see the logfile.");
                    break;
                }

                // This window has just been created while loading the layout
                if (pg->isChild("Text"))
                {
                    Window* txt = pg->getChild("Text");
                    txt->setText(PageText [num - 3]);

                    pg->setText(pgname.str().c_str());
                    tc->addTab(pg);

                    refreshPageList();
                    break;
                }
            }
        }

        return true;
    }

    bool handleGoto(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            ListboxItem* lbi = lbox->getFirstSelectedItem();

            if (lbi)
            {
                tc->setSelectedTab(lbi->getText());
            }
        }

        return true;
    }

    bool handleShow(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            ListboxItem* lbi = lbox->getFirstSelectedItem();

            if (lbi)
            {
                tc->makeTabVisible(lbi->getText());
            }
        }

        return true;
    }

    bool handleDel(const EventArgs&)
    {
        Window* root = d_guiContext->getRootWindow();
        // Check if the windows exists
        Listbox* lbox = 0;
        TabControl* tc = 0;

        if (root->isChild("Frame/TabControl/Page1/PageList"))
        {
            lbox = static_cast<Listbox*>(root->getChild(
                                             "Frame/TabControl/Page1/PageList"));
        }

        if (root->isChild("Frame/TabControl"))
        {
            tc = static_cast<TabControl*>(root->getChild(
                                              "Frame/TabControl"));
        }

        if (lbox && tc)
        {
            ListboxItem* lbi = lbox->getFirstSelectedItem();

            if (lbi)
            {
                Window* content = tc->getTabContents(lbi->getText());
                tc->removeTab(lbi->getText());
                // Remove the actual window from Cegui
                WindowManager::getSingleton().destroyWindow(content);

                refreshPageList();
            }
        }

        return true;
    }

    protected:
        CEGUI::GUIContext* d_guiContext;
};

/*************************************************************************
    Define the module function that returns an instance of the sample
*************************************************************************/
extern "C" SAMPLE_EXPORT Sample& getSampleInstance()
{
    static TabControlDemo sample;
    return sample;
}
<|endoftext|>