<commit_before>/*
TLD's work well w/ features (keypts) low-level features

- DoT works well with textureless objects (contoures)
- Use both to bootstrap a contour and features based reconstruction
- Does going to 3D from contour make tracking possible ??

*/
#define WINDOW_NAME "TLD Segmenter"

#include <set>
#include <bot_core/bot_core.h>
#include <bot_frames/bot_frames.h>
#include <bot_param/param_client.h>

#include <opencv2/opencv.hpp>

#include <image_io_utils/image_io_utils.hpp> // to simplify jpeg/zlib compression and decompression
#include <lcmtypes/perception_image_roi_t.h>
#include <ConciseArgs>

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;

int MAX_IMAGE_WIDTH = 0;
int MAX_IMAGE_HEIGHT = 0;

int32_t OBJECT_ID = 1;
int32_t FEATURE_ID = 1; // 1 for object (reference), -1 for virtual heading object
using namespace cv;

struct state_t {
    lcm_t *lcm;
    GMainLoop *mainloop;
    BotParam *param;
    BotFrames *frames;
    int counter;

    // Img
    cv::Mat img;

    // utimes for image
    int64_t  img_utime;

    // UI selection of desired object
    Rect selection, selection_virtual;
    Point origin, origin_virtual;
    bool selectObject, selectObject_virtual;

    state_t () {
        // LCM, BotFrames, BotParam inits
        lcm =  bot_lcm_get_global(NULL);
        param = bot_param_new_from_server(lcm, 1);
        frames = bot_frames_get_global (lcm, param);

        // Counter for debug prints
        counter = 0;

        selectObject = false;
        selectObject_virtual = false;
    }
    ~state_t () {
        lcm_destroy(lcm);
    }

};
state_t * state = NULL;

struct MouseEvent {
    MouseEvent() { event = -1; buttonState = 0; }
    Point pt;
    int event;
    int buttonState;
};
MouseEvent mouse;

static void onMouse(int event, int x, int y, int flags, void* userdata) {
    MouseEvent* data = (MouseEvent*)userdata;

    float sx = 1.f / WINDOW_WIDTH ;
    float sy = 1.f / WINDOW_HEIGHT;

    if (state->selectObject) {
        state->selection.x = MIN(x, state->origin.x);
        state->selection.y = MIN(y, state->origin.y);
        state->selection.width = std::abs(x - state->origin.x);
        state->selection.height = std::abs(y - state->origin.y);
        state->selection &= Rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    }

    if (state->selectObject_virtual) {
        state->selection_virtual.x = MIN(x, state->origin_virtual.x);
        state->selection_virtual.y = MIN(y, state->origin_virtual.y);
        state->selection_virtual.width = std::abs(x - state->origin_virtual.x);
        state->selection_virtual.height = std::abs(y - state->origin_virtual.y);
        state->selection &= Rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    }

    switch (event) {
    case CV_EVENT_RBUTTONDOWN:
        state->origin_virtual = Point(x, y);
        state->selection_virtual = Rect(x, y, 0, 0);
        state->selectObject_virtual = true;
        break;
    case CV_EVENT_RBUTTONUP:
        state->selectObject_virtual = false;
        std::cerr << "SEND virtual selection: " << state->img_utime << " - " <<
            state->selection_virtual.x << " " << state->selection_virtual.y << " " <<
            state->selection_virtual.width << " " << state->selection_virtual.height << std::endl;

        perception_image_roi_t img_vselection;
        img_vselection.utime = state->img_utime;
        img_vselection.object_id = OBJECT_ID;
        img_vselection.feature_id = -1; // FEATURE_ID;
        img_vselection.roi.x = state->selection_virtual.x * sx;
        img_vselection.roi.y = state->selection_virtual.y * sy;
        img_vselection.roi.width = state->selection_virtual.width * sx;
        img_vselection.roi.height = state->selection_virtual.height * sy;
        perception_image_roi_t_publish(state->lcm, "TLD_OBJECT_ROI", &img_vselection);

        // destroyWindow(WINDOW_NAME);
        // state->img = cv::Mat();

        break;
    case CV_EVENT_LBUTTONDOWN:
        state->origin = Point(x, y);
        state->selection = Rect(x, y, 0, 0);
        state->selectObject = true;

        // reset virtual feature
        state->selection_virtual = Rect(0,0,0,0);

        break;
    case CV_EVENT_LBUTTONUP:
        state->selectObject = false;
        std::cerr << "SEND selection: " << state->img_utime << " - " <<
            state->selection.x << " " << state->selection.y << " " <<
            state->selection.width << " " << state->selection.height << std::endl;

        perception_image_roi_t img_selection;
        img_selection.utime = state->img_utime;
        img_selection.object_id = OBJECT_ID;
        img_selection.feature_id = 1; // FEATURE_ID;
        img_selection.roi.x = state->selection.x * sx;
        img_selection.roi.y = state->selection.y * sy;
        img_selection.roi.width = state->selection.width * sx;
        img_selection.roi.height = state->selection.height * sy;
        perception_image_roi_t_publish(state->lcm, "TLD_OBJECT_ROI", &img_selection);
        // destroyWindow(WINDOW_NAME);
        // state->img = cv::Mat();

        break;
    }
    return;
}

void  INThandler(int sig)
{
    printf("Exiting\n");
    if (state) delete state;
    exit(0);
}

void
decode_image(const bot_core_image_t * msg, cv::Mat& img)
{
    int ch = msg->row_stride / (msg->width);
    if (img.empty() || img.rows != msg->height || img.cols != msg->width)
        if (ch == 3)
            img.create(msg->height, msg->width, CV_8UC3);
        else
            img.create(msg->height, msg->width, CV_8UC1);
    std::cerr << "msg: " << ch << " " << msg->row_stride << " " << msg->width << "x" << msg->height << std::endl;

  // extract image data
  switch (msg->pixelformat) {
    case BOT_CORE_IMAGE_T_PIXEL_FORMAT_RGB:
        memcpy(img.data, msg->data, sizeof(uint8_t) * msg->width * msg->height * 3);
        cv::cvtColor(img, img, CV_RGB2BGR);
      break;
    case BOT_CORE_IMAGE_T_PIXEL_FORMAT_MJPEG:
      // for some reason msg->row_stride is 0, so we use msg->width instead.
        if (ch == 3) {
            jpeg_decompress_8u_rgb(msg->data,
                                    msg->size,
                                    img.data,
                                    msg->width,
                                    msg->height,
                                    msg->width * ch);
        cv::cvtColor(img, img, CV_RGB2BGR);
        } else {
            jpeg_decompress_8u_gray(msg->data,
                                    msg->size,
                                    img.data,
                                    msg->width,
                                    msg->height,
                                    msg->width);
        }
      break;
  case BOT_CORE_IMAGE_T_PIXEL_FORMAT_GRAY:
      memcpy(img.data, msg->data, sizeof(uint8_t) * msg->width * msg->height);
      break;
    default:
      fprintf(stderr, "Unrecognized image format\n");
      break;
  }
  return;
}

static void on_image_frame (const lcm_recv_buf_t *rbuf, const char *channel,
                            const bot_core_image_t *msg,
                            void *user_data ) {

    if (!msg->width || !msg->height) return;

    if (!MAX_IMAGE_WIDTH || !MAX_IMAGE_HEIGHT) {
        MAX_IMAGE_WIDTH = msg->width;
        MAX_IMAGE_HEIGHT = msg->height;
    }

    state_t* state = (state_t*) user_data;
    if (state->img.empty() || state->img.rows != msg->height || state->img.cols != msg->width) {
        if (msg->pixelformat == BOT_CORE_IMAGE_T_PIXEL_FORMAT_GRAY) {
            std::cerr << "ERROR: Incoming image is grayscale!! Cannot perform color tracking!!!" << std::endl;
            assert(0);
        } else {
            std::cerr << "One time creation of image" << std::endl;
            state->img.create(msg->height, msg->width, CV_8UC3);
        }
    }
    decode_image(msg, state->img);
    state->img_utime = msg->utime;
    return;
}

struct TLDSegmenterOptions {
    bool vDEBUG;
    std::string vCHANNEL;

    TLDSegmenterOptions () :
        vCHANNEL(std::string("CAMERALEFT")), vDEBUG(false) {}
};
TLDSegmenterOptions options;

int main(int argc, char** argv)
{
    std::cout << "============= QUICK MODES ===================\n";
    std::cout << "drc-tld-segmenter -c CAMERALEFT\n";
    std::cout << "=============================================\n";

    ConciseArgs opt(argc, (char**)argv);
    opt.add(options.vCHANNEL, "c", "camera-channel","Camera Channel [CAMERALEFT]");
    opt.add(options.vDEBUG, "d", "debug","Debug mode");
    opt.parse();

    std::cerr << "===========  TLD Tracker ============" << std::endl;
    std::cerr << "=> CAMERA CHANNEL : " << options.vCHANNEL << std::endl;
    std::cerr << "=> DEBUG : " << options.vDEBUG << std::endl;
    std::cerr << "===============================================" << std::endl;

    // Install signal handler to free data.
    signal(SIGINT, INThandler);

    // Param server, botframes
    state = new state_t();

    cv::namedWindow( WINDOW_NAME );
    cv::setMouseCallback( WINDOW_NAME, onMouse, &mouse);

    // Subscriptions
    bot_core_image_t_subscribe(state->lcm, options.vCHANNEL.c_str(), on_image_frame, (void*)state);

    // Install signal handler to free data.
    signal(SIGINT, INThandler);

    while(1) {
        unsigned char c = cv::waitKey(1) & 0xff;
	lcm_handle(state->lcm);
        if (c == 'q') {
            break;
        // } else if (c == 'd') {
        //     FEATURE_ID++;
        // } else if (c == 'a') {
        //     FEATURE_ID--;
        } else if (c == 'w') {
            OBJECT_ID++;
        } else if (c == 's') {
            OBJECT_ID--;
        }

        // UI handling
        if (!state->img.empty()) {
            cv::Mat display;
            cv::resize(state->img.clone(), display, cv::Size(WINDOW_WIDTH,WINDOW_HEIGHT));
            if (state->selection.width > 0 && state->selection.height > 0) {

                cv::Mat roi(display, state->selection);
                rectangle(display, state->selection, cv::Scalar(0,255,255), 2);
                // bitwise_not(roi, roi);
            }
            if (state->selection_virtual.width > 0 && state->selection_virtual.height > 0) {

                cv::Mat roi(display, state->selection_virtual);
                rectangle(display, state->selection_virtual, cv::Scalar(0,255,0), 2);
                // bitwise_not(roi, roi);
            }

            // Show OBJECT_ID, FEATURE_ID
            cv::putText(display, cv::format("OBJ: %ld", OBJECT_ID),
                        Point(20,20), 0, .5, cv::Scalar(0,200,0), 2);

            imshow(WINDOW_NAME, display);
        }
    }

    if (state) delete state;
    return 0;
}
<commit_msg>tld-segmenter: moved lcm handle to separate thread<commit_after>/*
TLD's work well w/ features (keypts) low-level features

- DoT works well with textureless objects (contoures)
- Use both to bootstrap a contour and features based reconstruction
- Does going to 3D from contour make tracking possible ??

*/
#define WINDOW_NAME "TLD Segmenter"

#include <set>
#include <bot_core/bot_core.h>
#include <bot_frames/bot_frames.h>
#include <bot_param/param_client.h>

#include <opencv2/opencv.hpp>

#include <image_io_utils/image_io_utils.hpp> // to simplify jpeg/zlib compression and decompression
#include <lcmtypes/perception_image_roi_t.h>
#include <ConciseArgs>

const int WINDOW_WIDTH = 800;
const int WINDOW_HEIGHT = 800;

int MAX_IMAGE_WIDTH = 0;
int MAX_IMAGE_HEIGHT = 0;

int32_t OBJECT_ID = 1;
int32_t FEATURE_ID = 1; // 1 for object (reference), -1 for virtual heading object
using namespace cv;

struct state_t {
    lcm_t *lcm;
    pthread_t lcm_thread;
    pthread_mutex_t img_mutex;

    GMainLoop *mainloop;
    BotParam *param;
    BotFrames *frames;
    int counter;

    // Img
    cv::Mat img;

    // utimes for image
    int64_t  img_utime;

    // UI selection of desired object
    Rect selection, selection_virtual;
    Point origin, origin_virtual;
    bool selectObject, selectObject_virtual;

    state_t () {
        // LCM, BotFrames, BotParam inits
        lcm =  bot_lcm_get_global(NULL);
        param = bot_param_new_from_server(lcm, 1);
        frames = bot_frames_get_global (lcm, param);

        img_mutex = PTHREAD_MUTEX_INITIALIZER;
        // Counter for debug prints
        counter = 0;

        selectObject = false;
        selectObject_virtual = false;
    }
    ~state_t () {
    }

};
state_t * state = NULL;

void* lcm_thread_handler(void *l) {
    state_t* state = (state_t*)l;
    while(1)
        lcm_handle(state->lcm);

}
struct MouseEvent {
    MouseEvent() { event = -1; buttonState = 0; }
    Point pt;
    int event;
    int buttonState;
};
MouseEvent mouse;

static void onMouse(int event, int x, int y, int flags, void* userdata) {
    MouseEvent* data = (MouseEvent*)userdata;

    float sx = 1.f / WINDOW_WIDTH ;
    float sy = 1.f / WINDOW_HEIGHT;

    if (state->selectObject) {
        state->selection.x = MIN(x, state->origin.x);
        state->selection.y = MIN(y, state->origin.y);
        state->selection.width = std::abs(x - state->origin.x);
        state->selection.height = std::abs(y - state->origin.y);
        state->selection &= Rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    }

    if (state->selectObject_virtual) {
        state->selection_virtual.x = MIN(x, state->origin_virtual.x);
        state->selection_virtual.y = MIN(y, state->origin_virtual.y);
        state->selection_virtual.width = std::abs(x - state->origin_virtual.x);
        state->selection_virtual.height = std::abs(y - state->origin_virtual.y);
        state->selection &= Rect(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    }

    switch (event) {
    case CV_EVENT_RBUTTONDOWN:
        state->origin_virtual = Point(x, y);
        state->selection_virtual = Rect(x, y, 0, 0);
        state->selectObject_virtual = true;
        break;
    case CV_EVENT_RBUTTONUP:
        state->selectObject_virtual = false;
        std::cerr << "SEND virtual selection: " << state->img_utime << " - " <<
            state->selection_virtual.x << " " << state->selection_virtual.y << " " <<
            state->selection_virtual.width << " " << state->selection_virtual.height << std::endl;

        perception_image_roi_t img_vselection;
        img_vselection.utime = state->img_utime;
        img_vselection.object_id = OBJECT_ID;
        img_vselection.feature_id = -1; // FEATURE_ID;
        img_vselection.roi.x = state->selection_virtual.x * sx;
        img_vselection.roi.y = state->selection_virtual.y * sy;
        img_vselection.roi.width = state->selection_virtual.width * sx;
        img_vselection.roi.height = state->selection_virtual.height * sy;
        perception_image_roi_t_publish(state->lcm, "TLD_OBJECT_ROI", &img_vselection);

        // destroyWindow(WINDOW_NAME);
        // state->img = cv::Mat();

        break;
    case CV_EVENT_LBUTTONDOWN:
        state->origin = Point(x, y);
        state->selection = Rect(x, y, 0, 0);
        state->selectObject = true;

        // reset virtual feature
        state->selection_virtual = Rect(0,0,0,0);

        break;
    case CV_EVENT_LBUTTONUP:
        state->selectObject = false;
        std::cerr << "SEND selection: " << state->img_utime << " - " <<
            state->selection.x << " " << state->selection.y << " " <<
            state->selection.width << " " << state->selection.height << std::endl;

        perception_image_roi_t img_selection;
        img_selection.utime = state->img_utime;
        img_selection.object_id = OBJECT_ID;
        img_selection.feature_id = 1; // FEATURE_ID;
        img_selection.roi.x = state->selection.x * sx;
        img_selection.roi.y = state->selection.y * sy;
        img_selection.roi.width = state->selection.width * sx;
        img_selection.roi.height = state->selection.height * sy;
        perception_image_roi_t_publish(state->lcm, "TLD_OBJECT_ROI", &img_selection);
        // destroyWindow(WINDOW_NAME);
        // state->img = cv::Mat();

        break;
    }
    return;
}

void  INThandler(int sig)
{
    printf("Exiting\n");
    if (state) delete state;
    exit(0);
}

void
decode_image(const bot_core_image_t * msg, cv::Mat& img)
{
    int ch = msg->row_stride / (msg->width);
    if (img.empty() || img.rows != msg->height || img.cols != msg->width)
        if (ch == 3)
            img.create(msg->height, msg->width, CV_8UC3);
        else
            img.create(msg->height, msg->width, CV_8UC1);
    std::cerr << "msg: " << ch << " " << msg->row_stride << " " << msg->width << "x" << msg->height << std::endl;

  // extract image data
  switch (msg->pixelformat) {
    case BOT_CORE_IMAGE_T_PIXEL_FORMAT_RGB:
        memcpy(img.data, msg->data, sizeof(uint8_t) * msg->width * msg->height * 3);
        cv::cvtColor(img, img, CV_RGB2BGR);
      break;
    case BOT_CORE_IMAGE_T_PIXEL_FORMAT_MJPEG:
      // for some reason msg->row_stride is 0, so we use msg->width instead.
        if (ch == 3) {
            jpeg_decompress_8u_rgb(msg->data,
                                    msg->size,
                                    img.data,
                                    msg->width,
                                    msg->height,
                                    msg->width * ch);
        cv::cvtColor(img, img, CV_RGB2BGR);
        } else {
            jpeg_decompress_8u_gray(msg->data,
                                    msg->size,
                                    img.data,
                                    msg->width,
                                    msg->height,
                                    msg->width);
        }
      break;
  case BOT_CORE_IMAGE_T_PIXEL_FORMAT_GRAY:
      memcpy(img.data, msg->data, sizeof(uint8_t) * msg->width * msg->height);
      break;
    default:
      fprintf(stderr, "Unrecognized image format\n");
      break;
  }
  return;
}

static void on_image_frame (const lcm_recv_buf_t *rbuf, const char *channel,
                            const bot_core_image_t *msg,
                            void *user_data ) {

    if (!msg->width || !msg->height) return;

    if (!MAX_IMAGE_WIDTH || !MAX_IMAGE_HEIGHT) {
        MAX_IMAGE_WIDTH = msg->width;
        MAX_IMAGE_HEIGHT = msg->height;
    }

    pthread_mutex_lock(&state->img_mutex);
    state_t* state = (state_t*) user_data;
    if (state->img.empty() || state->img.rows != msg->height || state->img.cols != msg->width) {
        if (msg->pixelformat == BOT_CORE_IMAGE_T_PIXEL_FORMAT_GRAY) {
            std::cerr << "ERROR: Incoming image is grayscale!! Cannot perform color tracking!!!" << std::endl;
            assert(0);
        } else {
            std::cerr << "One time creation of image" << std::endl;
            state->img.create(msg->height, msg->width, CV_8UC3);
        }
    }
    decode_image(msg, state->img);
    state->img_utime = msg->utime;
    pthread_mutex_unlock(&state->img_mutex);
    return;
}

struct TLDSegmenterOptions {
    bool vDEBUG;
    std::string vCHANNEL;

    TLDSegmenterOptions () :
        vCHANNEL(std::string("CAMERALEFT")), vDEBUG(false) {}
};
TLDSegmenterOptions options;

int main(int argc, char** argv)
{
    std::cout << "============= QUICK MODES ===================\n";
    std::cout << "drc-tld-segmenter -c CAMERALEFT\n";
    std::cout << "=============================================\n";

    ConciseArgs opt(argc, (char**)argv);
    opt.add(options.vCHANNEL, "c", "camera-channel","Camera Channel [CAMERALEFT]");
    opt.add(options.vDEBUG, "d", "debug","Debug mode");
    opt.parse();

    std::cerr << "===========  TLD Tracker ============" << std::endl;
    std::cerr << "=> CAMERA CHANNEL : " << options.vCHANNEL << std::endl;
    std::cerr << "=> DEBUG : " << options.vDEBUG << std::endl;
    std::cerr << "===============================================" << std::endl;

    // Install signal handler to free data.
    signal(SIGINT, INThandler);

    // Param server, botframes
    state = new state_t();

    printf("starting lcm thread\n");
    pthread_create(&(state->lcm_thread), NULL, lcm_thread_handler, state);

    cv::namedWindow( WINDOW_NAME );
    cv::setMouseCallback( WINDOW_NAME, onMouse, &mouse);

    // Subscriptions
    bot_core_image_t_subscribe(state->lcm, options.vCHANNEL.c_str(), on_image_frame, (void*)state);

    // Install signal handler to free data.
    signal(SIGINT, INThandler);

    while(1) {
        unsigned char c = cv::waitKey(1) & 0xff;
	// lcm_handle(state->lcm);
        if (c == 'q') {
            break;
        // } else if (c == 'd') {
        //     FEATURE_ID++;
        // } else if (c == 'a') {
        //     FEATURE_ID--;
        } else if (c == 'w') {
            OBJECT_ID++;
        } else if (c == 's') {
            OBJECT_ID--;
        }

        pthread_mutex_lock(&state->img_mutex);
        // UI handling
        if (!state->img.empty()) {
            cv::Mat display;
            cv::resize(state->img.clone(), display, cv::Size(WINDOW_WIDTH,WINDOW_HEIGHT));
            if (state->selection.width > 0 && state->selection.height > 0) {

                cv::Mat roi(display, state->selection);
                rectangle(display, state->selection, cv::Scalar(0,255,255), 2);
                // bitwise_not(roi, roi);
            }
            if (state->selection_virtual.width > 0 && state->selection_virtual.height > 0) {

                cv::Mat roi(display, state->selection_virtual);
                rectangle(display, state->selection_virtual, cv::Scalar(0,255,0), 2);
                // bitwise_not(roi, roi);
            }

            // Show OBJECT_ID, FEATURE_ID
            cv::putText(display, cv::format("OBJ: %ld", OBJECT_ID),
                        Point(20,20), 0, .5, cv::Scalar(0,200,0), 2);

            imshow(WINDOW_NAME, display);
        }
        pthread_mutex_unlock(&state->img_mutex);
    }

    // if (state) delete state;
    return 0;
}
<|endoftext|>


<commit_before>/***************************************************************************
                          irccontact.cpp  -  description
                             -------------------
    begin                : Wed Mar 6 2002
    copyright            : (C) 2002 by nbetcher
    email                : nbetcher@usinternet.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "irccontact.h"
#include <kmessagebox.h>
#include <qlayout.h>
#include <kdialog.h>
#include <kdebug.h>
#include <kconfig.h>
#include <ktabctl.h>
#include <kstddirs.h>
#include <ircchatwindow.h>

IRCContact::IRCContact(QListViewItem *parent, const QString &server, const QString &target, unsigned int port, bool joinOnConnect, IRCServerContact *contact)
	: IMContact(parent)
{
	engine = contact->engine;
	requestedQuit = false;
	KGlobal::config()->setGroup("IRC");
	QString newServer;
	if (server.isEmpty() == true)
	{
		newServer = KGlobal::config()->readEntry("Server", "irc.openprojects.net");
		mServer = newServer;
	} else {
		mServer = server;
	}
	if (port == 0)
	{
		unsigned int port = KGlobal::config()->readEntry("Port", "6667").toUInt();
	}
	QString user = "kopeteuser";
	QString nick = KGlobal::config()->readEntry("Nickname", "KopeteUser");

	mContact = contact;
	mTarget = target;
	mPort = port;
	mUsername = user;
	mNickname = nick;
	mJoinOnConnect = joinOnConnect;

	if (target[0] == '#' || target[0] == '!' || target[0] == '&')
	{
		setPixmap(0, locate("data", "kopete/pics/irc_privmsg.xpm"));
		QString oldTarget = mTarget;
		mTarget = mTarget.remove(0,1);
		setText(0, mTarget);
		mTarget = oldTarget;
	} else {
		setText(0, mTarget);
	}

	connect(mContact, SIGNAL(quittingServer()), this, SLOT(slotServerIsQuitting()));
	connect(mContact, SIGNAL(serverQuit()), this, SLOT(slotServerHasQuit()));
	connect(mContact->engine, SIGNAL(incomingPartedChannel(const QString &, const QString &, const QString &)), this, SLOT(slotPartedChannel(const QString &, const QString &, const QString &)));
	if (joinOnConnect == true)
	{
		if (mContact->engine->isLoggedIn() == true)
		{
			joinNow();
		} else {
			QObject::connect(mContact->engine, SIGNAL(connectedToServer()), this, SLOT(joinNow()));
		}
	}
}

void IRCContact::slotServerHasQuit()
{
	delete this;
}

void IRCContact::slotServerIsQuitting()
{
	if (requestedQuit == false)
	{
		QColor color(175, 8, 8);
		QString partWarning = "Attempting to quit server. If this takes an unusual amount of time, please right click on one of the channels or server in Kopete contact list and click \"Quit IRC Server\" again.
");
		chatView->chatView->append(partWarning);
		chatView->chatView->scrollToBottom();
	}
}

void IRCContact::rightButtonPressed(const QPoint &point)
{
	popup = new KPopupMenu();
	popup->insertTitle(mTarget);
	popup->insertItem("Part", this, SLOT(slotPart()));
// TODO:	popup->insertItem("Hop (Part and Re-join)", this, SLOT(slotHop()));
// TODO:	popup->insertItem("Remove", this, SLOT(slotRemoveThis()));
	popup->insertTitle(((QListViewItem *)mContact)->text(0));
	popup->insertItem("Quit IRC Server", this, SLOT(slotQuitServer()));
	popup->popup(point);
}

void IRCContact::slotQuitServer()
{
	requestedQuit = true;
	mContact->slotQuitServer();
}

void IRCContact::leftButtonDoubleClicked()
{
	if (chatView != 0)
	{
		if (mContact->mWindow->isVisible() == true)
		{
			mContact->mWindow->raise();
			chatView->setFocus();
			chatView->messageBox->setFocus();
		}
	}
}

void IRCContact::slotPart()
{
	if (chatView != 0)
	{
		QColor color(175, 8, 8);
		QString partWarning = "Attempting to part channel. If this takes an unusual amount of time, please click the close button on this window again, or right click on the contact in the Kopete window and click \"Part\" again.
");
		chatView->chatView->append(partWarning);
		chatView->chatView->scrollToBottom();
	}
	waitingPart = true;
	mContact->engine->partChannel(QCString(mTarget.local8Bit()) ,QString("Using Kopete IRC Plugin"));
}

void IRCContact::slotPartedChannel(const QString &originating, const QString &channel, const QString &reason)
{
	if (mTarget.lower() == channel.lower() && originating.left(originating.find("!")).lower() == mContact->mNickname.lower())
	{
		unloading();
	}
}

void IRCContact::unloading()
{
	if (chatView != 0)
	{
		delete chatView;
	}
	mContact->unloading();
	delete this;
}

void IRCContact::slotIncomingMotd(const QString &motd)
{

}

void IRCContact::joinNow()
{

	mChatViewContainer = new QFrame(mContact->mWindow->mChannelsTabCtl);
	mChatViewContainer->resize(300,300);
	kdDebug() << "FUCK PART 1" << endl;
	(new QVBoxLayout(mChatViewContainer, KDialog::marginHint(), KDialog::spacingHint()))->setAutoAdd(true);
	(void)new QLabel(i18n("Test :-):"),mChatViewContainer );
    kdDebug() << "FUCK PART 2" << endl;
	chatView = new IRCChatView(mServer, mTarget, this, mChatViewContainer);
	kdDebug() << "FUCK PART 3" << endl;
	mContact->mWindow->mChannelsTabCtl->addTab(mChatViewContainer, mTarget);
    mContact->mWindow->adjustSize();
	mContact->mWindow->show();
	mChatViewContainer->show();
	chatView->show();
	kdDebug() << "FUCK PART 4" << endl;
	QObject::connect(mContact->engine, SIGNAL(userJoinedChannel(const QString &, const QString &)), chatView, SLOT(userJoinedChannel(const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingMessage(const QString &, const QString &, const QString &)), chatView, SLOT(incomingMessage(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingPartedChannel(const QString &, const QString &, const QString &)), chatView, SLOT(userPartedChannel(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingNamesList(const QString &, const QString &, const int)), chatView, SLOT(incomingNamesList(const QString &, const QString &, const int)));
	QObject::connect(mContact->engine, SIGNAL(incomingAction(const QString &, const QString &, const QString &)), chatView, SLOT(incomingAction(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingQuitIRC(const QString &,  const QString &)), chatView, SLOT(userQuitIRC(const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingNickChange(const QString &,  const QString &)), chatView, SLOT(nickNameChanged(const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingTopicChange(const QString &, const QString &, const QString &)), chatView, SLOT(incomingNewTopic(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingExistingTopic(const QString &,  const QString &)), chatView, SLOT(receivedExistingTopic(const QString &, const QString &)));
}
<commit_msg><commit_after>/***************************************************************************
                          irccontact.cpp  -  description
                             -------------------
    begin                : Wed Mar 6 2002
    copyright            : (C) 2002 by nbetcher
    email                : nbetcher@usinternet.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include "irccontact.h"
#include <kmessagebox.h>
#include <qlayout.h>
#include <kdialog.h>
#include <kdebug.h>
#include <kconfig.h>
#include <ktabctl.h>
#include <kstddirs.h>
#include <ircchatwindow.h>

IRCContact::IRCContact(QListViewItem *parent, const QString &server, const QString &target, unsigned int port, bool joinOnConnect, IRCServerContact *contact)
	: IMContact(parent)
{
	engine = contact->engine;
	requestedQuit = false;
	KGlobal::config()->setGroup("IRC");
	QString newServer;
	if (server.isEmpty() == true)
	{
		newServer = KGlobal::config()->readEntry("Server", "irc.openprojects.net");
		mServer = newServer;
	} else {
		mServer = server;
	}
	if (port == 0)
	{
		unsigned int port = KGlobal::config()->readEntry("Port", "6667").toUInt();
	}
	QString user = "kopeteuser";
	QString nick = KGlobal::config()->readEntry("Nickname", "KopeteUser");

	mContact = contact;
	mTarget = target;
	mPort = port;
	mUsername = user;
	mNickname = nick;
	mJoinOnConnect = joinOnConnect;

	if (target[0] == '#' || target[0] == '!' || target[0] == '&')
	{
		setPixmap(0, locate("data", "kopete/pics/irc_privmsg.xpm"));
		QString oldTarget = mTarget;
		mTarget = mTarget.remove(0,1);
		setText(0, mTarget);
		mTarget = oldTarget;
	} else {
		setText(0, mTarget);
	}

	connect(mContact, SIGNAL(quittingServer()), this, SLOT(slotServerIsQuitting()));
	connect(mContact, SIGNAL(serverQuit()), this, SLOT(slotServerHasQuit()));
	connect(mContact->engine, SIGNAL(incomingPartedChannel(const QString &, const QString &, const QString &)), this, SLOT(slotPartedChannel(const QString &, const QString &, const QString &)));
	if (joinOnConnect == true)
	{
		if (mContact->engine->isLoggedIn() == true)
		{
			joinNow();
		} else {
			QObject::connect(mContact->engine, SIGNAL(connectedToServer()), this, SLOT(joinNow()));
		}
	}
}

void IRCContact::slotServerHasQuit()
{
	delete this;
}

void IRCContact::slotServerIsQuitting()
{
	if (requestedQuit == false)
	{
		QColor color(175, 8, 8);
		QString partWarning = "Attempting to quit server. If this takes an unusual amount of time, please right click on one of the channels or server in Kopete contact list and click \"Quit IRC Server\" again.
");
		chatView->chatView->append(partWarning);
		chatView->chatView->scrollToBottom();
	}
}

void IRCContact::rightButtonPressed(const QPoint &point)
{
	popup = new KPopupMenu();
	popup->insertTitle(mTarget);
	popup->insertItem("Part", this, SLOT(slotPart()));
// TODO:	popup->insertItem("Hop (Part and Re-join)", this, SLOT(slotHop()));
// TODO:	popup->insertItem("Remove", this, SLOT(slotRemoveThis()));
	popup->insertTitle(((QListViewItem *)mContact)->text(0));
	popup->insertItem("Quit IRC Server", this, SLOT(slotQuitServer()));
	popup->popup(point);
}

void IRCContact::slotQuitServer()
{
	requestedQuit = true;
	mContact->slotQuitServer();
}

void IRCContact::leftButtonDoubleClicked()
{
	if (chatView != 0)
	{
		if (mContact->mWindow->isVisible() == true)
		{
			mContact->mWindow->raise();
			chatView->setFocus();
			chatView->messageBox->setFocus();
		}
	}
}

void IRCContact::slotPart()
{
	if (chatView != 0)
	{
		QColor color(175, 8, 8);
		QString partWarning = "Attempting to part channel. If this takes an unusual amount of time, please click the close button on this window again, or right click on the contact in the Kopete window and click \"Part\" again.
");
		chatView->chatView->append(partWarning);
		chatView->chatView->scrollToBottom();
	}
	waitingPart = true;
	mContact->engine->partChannel(QCString(mTarget.local8Bit()) ,QString("Using Kopete IRC Plugin"));
}

void IRCContact::slotPartedChannel(const QString &originating, const QString &channel, const QString &reason)
{
	if (mTarget.lower() == channel.lower() && originating.left(originating.find("!")).lower() == mContact->mNickname.lower())
	{
		unloading();
	}
}

void IRCContact::unloading()
{
	if (chatView != 0)
	{
		delete chatView;
	}
	mContact->unloading();
	delete this;
}

void IRCContact::slotIncomingMotd(const QString &motd)
{

}

void IRCContact::joinNow()
{

	/* This is a frame inside the tab, where we put the widgets in */
	mChatViewContainer = new QFrame(mContact->mWindow->mChannelsTabCtl);
	mChatViewContainer->resize(640,480);
	kdDebug() << "FUCK PART 1" << endl;
	QVBoxLayout *containerLayout;
	containerLayout = new QVBoxLayout(mChatViewContainer);
	//(void)new QLabel(i18n("Test :-):"),mChatViewContainer );
    //(void)new QLabel(i18n("Test :-):"), mContact->mWindow->mChannelsTabCtl);

	kdDebug() << "FUCK PART 2" << endl;
	chatView = new IRCChatView(mServer, mTarget, this, mChatViewContainer);
	containerLayout->addWidget(chatView);
	//chatView = new IRCChatView(mServer, mTarget, this, mContact->mWindow->mChannelsTabCtl );
	kdDebug() << "FUCK PART 3" << endl;
	mContact->mWindow->mChannelsTabCtl->addTab(mChatViewContainer, mTarget);
    //mContact->mWindow->mChannelsTabCtl->addTab(mContact->mWindow->mChannelsTabCtl, mTarget);

	//mContact->mWindow->adjustSize();
	mContact->mWindow->show();
	mChatViewContainer->show();
	chatView->show();
	kdDebug() << "FUCK PART 4" << endl;
	QObject::connect(mContact->engine, SIGNAL(userJoinedChannel(const QString &, const QString &)), chatView, SLOT(userJoinedChannel(const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingMessage(const QString &, const QString &, const QString &)), chatView, SLOT(incomingMessage(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingPartedChannel(const QString &, const QString &, const QString &)), chatView, SLOT(userPartedChannel(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingNamesList(const QString &, const QString &, const int)), chatView, SLOT(incomingNamesList(const QString &, const QString &, const int)));
	QObject::connect(mContact->engine, SIGNAL(incomingAction(const QString &, const QString &, const QString &)), chatView, SLOT(incomingAction(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingQuitIRC(const QString &,  const QString &)), chatView, SLOT(userQuitIRC(const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingNickChange(const QString &,  const QString &)), chatView, SLOT(nickNameChanged(const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingTopicChange(const QString &, const QString &, const QString &)), chatView, SLOT(incomingNewTopic(const QString &, const QString &, const QString &)));
	QObject::connect(mContact->engine, SIGNAL(incomingExistingTopic(const QString &,  const QString &)), chatView, SLOT(receivedExistingTopic(const QString &, const QString &)));
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2018 Rokas Kupstys
//
// 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 OR COPYRIGHT HOLDERS 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 "Widgets.h"
#include <ImGui/imgui_internal.h>
#include <Urho3D/Core/Context.h>
#include <Urho3D/Input/Input.h>
#include <SDL/SDL_scancode.h>
#include <Urho3D/SystemUI/SystemUI.h>

using namespace Urho3D;
using namespace ui::litterals;

namespace ImGui
{

const unsigned UISTATE_EXPIRATION_MS = 30000;

struct UIStateWrapper
{
    void Set(void* state, void(*deleter)(void*)=nullptr)
    {
        state_ = state;
        deleter_ = deleter;
    }

    void Unset()
    {
        if (deleter_ && state_)
            deleter_(state_);
        state_ = nullptr;
        deleter_ = nullptr;
    }

    void* Get(bool keepAlive=true)
    {
        if (keepAlive)
            timer_.Reset();
        return state_;
    }

    bool IsExpired()
    {
        return timer_.GetMSec(false) >= UISTATE_EXPIRATION_MS;
    }

protected:
    /// User state pointer.
    void* state_ = nullptr;
    /// Function that handles deleting state object when it becomes unused.
    void(*deleter_)(void* state) = nullptr;
    /// Timer which determines when state expires.
    Timer timer_;
};

HashMap<ImGuiID, UIStateWrapper> uiState_;

void SetUIStateP(void* state, void(*deleter)(void*))
{
    auto id = ui::GetCurrentWindow()->IDStack.back();
    uiState_[id].Set(state, deleter);
}

void* GetUIStateP()
{
    void* result = nullptr;
    auto id = ui::GetCurrentWindow()->IDStack.back();
    auto it = uiState_.Find(id);
    if (it != uiState_.End())
        result = it->second_.Get();

    // Every 30s check all saved states and remove expired ones.
    static Timer gcTimer;
    if (gcTimer.GetMSec(false) > UISTATE_EXPIRATION_MS)
    {
        gcTimer.Reset();

        for (auto jt = uiState_.Begin(); jt != uiState_.End();)
        {
            if (jt->second_.IsExpired())
            {
                jt->second_.Unset();
                jt = uiState_.Erase(jt);
            }
            else
                ++jt;
        }
    }

    return result;
}

void ExpireUIStateP()
{
    auto it = uiState_.Find(ui::GetCurrentWindow()->IDStack.back());
    if (it != uiState_.End())
    {
        it->second_.Unset();
        uiState_.Erase(it);
    }
}

int DoubleClickSelectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size)
{
    bool wasSelected = p_selected && *p_selected;
    if (ui::Selectable(label, p_selected, flags | ImGuiSelectableFlags_AllowDoubleClick, size))
    {
        if (wasSelected && ui::IsMouseDoubleClicked(MOUSEB_LEFT))
            return 2;
        else
            return 1;
    }
    if (ui::IsItemHovered() && ui::IsMouseClicked(MOUSEB_RIGHT))
    {
        *p_selected = true;
        return 1;
    }
    return 0;
}

int DoubleClickSelectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size)
{
    return DoubleClickSelectable(label, &selected, flags, size);
}

bool CollapsingHeaderSimple(const char* label, ImGuiTreeNodeFlags flags)
{
    ImGuiWindow* window = ui::GetCurrentWindow();
    if (window->SkipItems)
        return false;

    ui::PushStyleColor(ImGuiCol_HeaderActive, 0);
    ui::PushStyleColor(ImGuiCol_HeaderHovered, 0);
    ui::PushStyleColor(ImGuiCol_Header, 0);
    bool open = ui::TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_NoAutoOpenOnLog | ImGuiTreeNodeFlags_NoTreePushOnOpen, label);
    ui::PopStyleColor(3);
    return open;
}

bool ToolbarButton(const char* label)
{
    auto& g = *ui::GetCurrentContext();
    float dimension = g.FontBaseSize + g.Style.FramePadding.y * 2.0f;
    return ui::ButtonEx(label, {0, dimension}, ImGuiButtonFlags_PressedOnClick);
}

void SetHelpTooltip(const char* text, Key requireKey)
{
    unsigned scancode = requireKey & (~SDLK_SCANCODE_MASK);
    if (ui::IsItemHovered() && (requireKey == KEY_UNKNOWN || ui::IsKeyDown(scancode)))
        ui::SetTooltip("%s", text);
}

bool IconButton(const char* label)
{
    float size = ui::GetItemRectSize().y;
    return ui::Button(label, {size, size});
}

bool MaskSelector(unsigned int* mask)
{
    bool modified = false;
    auto style = ui::GetStyle();
    auto pos = ui::GetCursorPos();

    for (auto row = 0; row < 2; row++)
    {
        for (auto col = 0; col < 16; col++)
        {
            auto bitPosition = row * 16 + col;
            int bitMask = 1 << bitPosition;
            bool selected = (*mask & bitMask) != 0;
            if (selected)
            {
                ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_ButtonActive]);
                ui::PushStyleColor(ImGuiCol_ButtonHovered, style.Colors[ImGuiCol_ButtonActive]);
            }
            else
            {
                ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_Button]);
                ui::PushStyleColor(ImGuiCol_ButtonHovered, style.Colors[ImGuiCol_Button]);
            }

            ui::PushID(bitMask);
            if (ui::Button("", {8_dpx, 9_dpy}))
            {
                modified = true;
                *mask ^= bitMask;
            }
            if (ui::IsItemHovered())
                ui::SetTooltip("%d", bitPosition);
            ui::PopID();
            ui::SameLine(0, 0);
            ui::PopStyleColor(2);
        }
        ui::NewLine();
        if (row < 1)
            ui::SetCursorPos({pos.x, pos.y + 9_dpy});
    }

    return modified;
}

enum TransformResizeType
{
    RESIZE_NONE = 0,
    RESIZE_LEFT = 1,
    RESIZE_RIGHT = 2,
    RESIZE_TOP = 4,
    RESIZE_BOTTOM = 8,
    RESIZE_MOVE = 15,
};

}
/// Flag manipuation operators.
URHO3D_FLAGSET_EX(ImGui, TransformResizeType, TransformResizeTypeFlags);

namespace ImGui
{
/// Hashing function which enables use of enum type as a HashMap key.
inline unsigned MakeHash(const TransformResizeType& value) { return value; }

bool TransformRect(IntRect& inOut, TransformSelectorFlags flags)
{
    IntRect delta;
    return TransformRect(inOut, delta, flags);
}

bool TransformRect(Urho3D::IntRect& inOut, Urho3D::IntRect& delta, TransformSelectorFlags flags)
{
    struct State
    {
        /// A flag indicating type of resize action currently in progress
        TransformResizeTypeFlags resizing_ = RESIZE_NONE;
        /// A cache of system cursors
        HashMap<TransformResizeTypeFlags, SDL_Cursor*> cursors_;
        /// Default cursor shape
        SDL_Cursor* cursorArrow_;
        /// Flag indicating that this selector set cursor handle
        bool ownsCursor_ = false;

        State()
        {
            cursors_[RESIZE_MOVE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
            cursors_[RESIZE_LEFT] = cursors_[RESIZE_RIGHT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
            cursors_[RESIZE_BOTTOM] = cursors_[RESIZE_TOP] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
            cursors_[RESIZE_TOP | RESIZE_LEFT] = cursors_[RESIZE_BOTTOM | RESIZE_RIGHT] = SDL_CreateSystemCursor(
                SDL_SYSTEM_CURSOR_SIZENWSE);
            cursors_[RESIZE_TOP | RESIZE_RIGHT] = cursors_[RESIZE_BOTTOM | RESIZE_LEFT] = SDL_CreateSystemCursor(
                SDL_SYSTEM_CURSOR_SIZENESW);
            cursorArrow_ = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
        }

        ~State()
        {
            SDL_FreeCursor(cursorArrow_);
            for (const auto& it : cursors_)
                SDL_FreeCursor(it.second_);
        }
    };

    Input* input = ui::GetSystemUI()->GetSubsystem<Input>();

    auto renderHandle = [&](IntVector2 screenPos, int wh) -> bool {
        IntRect rect(
            screenPos.x_ - wh / 2,
            screenPos.y_ - wh / 2,
            screenPos.x_ + wh / 2,
            screenPos.y_ + wh / 2
        );

        if (!(flags & TSF_HIDEHANDLES))
        {
            ui::GetWindowDrawList()->AddRectFilled(ToImGui(rect.Min()), ToImGui(rect.Max()),
                ui::GetColorU32(ToImGui(Color::RED)));
        }

        return rect.IsInside(input->GetMousePosition()) == INSIDE;
    };

    auto size = inOut.Size();
    auto handleSize = Max(Min(Min(size.x_ / 4, size.y_ / 4), 8), 2);
    bool modified = false;

    auto* s = ui::GetUIState<State>();
    auto id = ui::GetID(s);

    // Extend rect to cover resize handles that are sticking out of ui element boundaries.
    auto extendedRect = inOut + IntRect(-handleSize / 2, -handleSize / 2, handleSize / 2, handleSize / 2);
    ui::ItemSize(ToImGui(inOut));
    if (ui::ItemAdd(ToImGui(extendedRect), id))
    {
        TransformResizeTypeFlags resizing = RESIZE_NONE;
        if (renderHandle(inOut.Min() + size / 2, handleSize))
            resizing = RESIZE_MOVE;

        bool canResizeHorizontal = !(flags & TSF_NOHORIZONTAL);
        bool canResizeVertical = !(flags & TSF_NOVERTICAL);

        if (canResizeHorizontal && canResizeVertical)
        {
            if (renderHandle(inOut.Min(), handleSize))
                resizing = RESIZE_LEFT | RESIZE_TOP;
            if (renderHandle(inOut.Min() + IntVector2(0, size.y_), handleSize))
                resizing = RESIZE_LEFT | RESIZE_BOTTOM;
            if (renderHandle(inOut.Min() + IntVector2(size.x_, 0), handleSize))
                resizing = RESIZE_TOP | RESIZE_RIGHT;
            if (renderHandle(inOut.Max(), handleSize))
                resizing = RESIZE_BOTTOM | RESIZE_RIGHT;
        }

        if (canResizeHorizontal)
        {
            if (renderHandle(inOut.Min() + IntVector2(0, size.y_ / 2), handleSize))
                resizing = RESIZE_LEFT;
            if (renderHandle(inOut.Min() + IntVector2(size.x_, size.y_ / 2), handleSize))
                resizing = RESIZE_RIGHT;
        }

        if (canResizeVertical)
        {
            if (renderHandle(inOut.Min() + IntVector2(size.x_ / 2, 0), handleSize))
                resizing = RESIZE_TOP;
            if (renderHandle(inOut.Min() + IntVector2(size.x_ / 2, size.y_), handleSize))
                resizing = RESIZE_BOTTOM;
        }

        // Draw rect around selected element
        ui::GetWindowDrawList()->AddRect(ToImGui(inOut.Min()), ToImGui(inOut.Max()),
            ui::GetColorU32(ToImGui(Color::RED)));

        // Reset mouse cursor if we are not hovering any handle and are not resizing
        if (resizing == RESIZE_NONE && s->resizing_ == RESIZE_NONE && s->ownsCursor_)
        {
            SDL_SetCursor(s->cursorArrow_);
            s->ownsCursor_ = false;
        }

        // Prevent interaction when something else blocks inactive transform.
        if (s->resizing_ != RESIZE_NONE || (ui::IsItemHovered(ImGuiHoveredFlags_RectOnly) &&
            (!ui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) || ui::IsWindowHovered())))
        {
            // Set mouse cursor if handle is hovered or if we are resizing
            if (resizing != RESIZE_NONE && !s->ownsCursor_)
            {
                SDL_SetCursor(s->cursors_[resizing]);
                s->ownsCursor_ = true;
            }

            // Begin resizing
            if (ui::IsMouseClicked(0))
                s->resizing_ = resizing;

            IntVector2 d = ToIntVector2(ui::GetIO().MouseDelta);
            if (s->resizing_ != RESIZE_NONE)
            {
                ui::SetActiveID(id, ui::GetCurrentWindow());
                if (!ui::IsMouseDown(0))
                    s->resizing_ = RESIZE_NONE;
                else if (d != IntVector2::ZERO)
                {
                    delta = IntRect::ZERO;

                    if (s->resizing_ == RESIZE_MOVE)
                    {
                        delta.left_ += d.x_;
                        delta.right_ += d.x_;
                        delta.top_ += d.y_;
                        delta.bottom_ += d.y_;
                        modified = true;
                    }
                    else
                    {
                        if (s->resizing_ & RESIZE_LEFT)
                        {
                            delta.left_ += d.x_;
                            modified = true;
                        }
                        else if (s->resizing_ & RESIZE_RIGHT)
                        {
                            delta.right_ += d.x_;
                            modified = true;
                        }

                        if (s->resizing_ & RESIZE_TOP)
                        {
                            delta.top_ += d.y_;
                            modified = true;
                        }
                        else if (s->resizing_ & RESIZE_BOTTOM)
                        {
                            delta.bottom_ += d.y_;
                            modified = true;
                        }
                    }
                }
            }
            else if (ui::IsItemActive())
                ui::SetActiveID(0, ui::GetCurrentWindow());

            if (modified)
                inOut += delta;
        }
        else if (ui::IsItemActive())
            ui::SetActiveID(0, ui::GetCurrentWindow());
    }
    return modified;
}

SystemUI* GetSystemUI()
{
    return static_cast<SystemUI*>(ui::GetIO().UserData);
}

bool EditorToolbarButton(const char* text, const char* tooltip, bool active)
{
    const auto& style = ui::GetStyle();
    if (active)
        ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_ButtonActive]);
    else
        ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_Button]);
    bool result = ui::ToolbarButton(text);
    ui::PopStyleColor();
    ui::SameLine(0, 0);
    if (ui::IsItemHovered() && tooltip)
        ui::SetTooltip("%s", tooltip);
    return result;
}

void OpenTreeNode(ImGuiID id)
{
    auto& storage = ui::GetCurrentWindow()->DC.StateStorage;
    if (!storage->GetInt(id))
    {
        storage->SetInt(id, true);
        ui::TreePushRawID(id);
    }
}

}
<commit_msg>Toolbox/SystemUI: Replace timer-based ui state expiration with frame-based expiration. Items unused for two frames in a row are deleted.<commit_after>//
// Copyright (c) 2018 Rokas Kupstys
//
// 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 OR COPYRIGHT HOLDERS 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 "Widgets.h"
#include <ImGui/imgui_internal.h>
#include <Urho3D/Core/Context.h>
#include <Urho3D/Input/Input.h>
#include <SDL/SDL_scancode.h>
#include <Urho3D/SystemUI/SystemUI.h>

using namespace Urho3D;
using namespace ui::litterals;

namespace ImGui
{

struct UIStateWrapper
{
    void Set(void* state, void(*deleter)(void*)=nullptr)
    {
        lastUse_ = ui::GetCurrentContext()->FrameCount;
        state_ = state;
        deleter_ = deleter;
    }

    void Unset()
    {
        if (deleter_ && state_)
            deleter_(state_);
        state_ = nullptr;
        deleter_ = nullptr;
    }

    void* Get()
    {
        lastUse_ = ui::GetCurrentContext()->FrameCount;
        return state_;
    }

    bool IsExpired()
    {
        return (ui::GetCurrentContext()->FrameCount - lastUse_) > 1;
    }

protected:
    /// User state pointer.
    void* state_ = nullptr;
    /// Function that handles deleting state object when it becomes unused.
    void(*deleter_)(void* state) = nullptr;
    /// Frame when value was last used.
    int lastUse_ = 0;
};

static HashMap<ImGuiID, UIStateWrapper> uiState_;
static int uiStateLastGcFrame_ = 0;

void SetUIStateP(void* state, void(*deleter)(void*))
{
    auto id = ui::GetCurrentWindow()->IDStack.back();
    uiState_[id].Set(state, deleter);
}

void* GetUIStateP()
{
    void* result = nullptr;
    auto id = ui::GetCurrentWindow()->IDStack.back();
    auto it = uiState_.Find(id);
    if (it != uiState_.End())
        result = it->second_.Get();

    int currentFrame = ui::GetCurrentContext()->FrameCount;
    if (uiStateLastGcFrame_ != currentFrame)
    {
        uiStateLastGcFrame_ = currentFrame;
        for (auto jt = uiState_.Begin(); jt != uiState_.End();)
        {
            if (jt->second_.IsExpired())
            {
                jt->second_.Unset();
                jt = uiState_.Erase(jt);
            }
            else
                ++jt;
        }
    }

    return result;
}

void ExpireUIStateP()
{
    auto it = uiState_.Find(ui::GetCurrentWindow()->IDStack.back());
    if (it != uiState_.End())
    {
        it->second_.Unset();
        uiState_.Erase(it);
    }
}

int DoubleClickSelectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags, const ImVec2& size)
{
    bool wasSelected = p_selected && *p_selected;
    if (ui::Selectable(label, p_selected, flags | ImGuiSelectableFlags_AllowDoubleClick, size))
    {
        if (wasSelected && ui::IsMouseDoubleClicked(MOUSEB_LEFT))
            return 2;
        else
            return 1;
    }
    if (ui::IsItemHovered() && ui::IsMouseClicked(MOUSEB_RIGHT))
    {
        *p_selected = true;
        return 1;
    }
    return 0;
}

int DoubleClickSelectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size)
{
    return DoubleClickSelectable(label, &selected, flags, size);
}

bool CollapsingHeaderSimple(const char* label, ImGuiTreeNodeFlags flags)
{
    ImGuiWindow* window = ui::GetCurrentWindow();
    if (window->SkipItems)
        return false;

    ui::PushStyleColor(ImGuiCol_HeaderActive, 0);
    ui::PushStyleColor(ImGuiCol_HeaderHovered, 0);
    ui::PushStyleColor(ImGuiCol_Header, 0);
    bool open = ui::TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_NoAutoOpenOnLog | ImGuiTreeNodeFlags_NoTreePushOnOpen, label);
    ui::PopStyleColor(3);
    return open;
}

bool ToolbarButton(const char* label)
{
    auto& g = *ui::GetCurrentContext();
    float dimension = g.FontBaseSize + g.Style.FramePadding.y * 2.0f;
    return ui::ButtonEx(label, {0, dimension}, ImGuiButtonFlags_PressedOnClick);
}

void SetHelpTooltip(const char* text, Key requireKey)
{
    unsigned scancode = requireKey & (~SDLK_SCANCODE_MASK);
    if (ui::IsItemHovered() && (requireKey == KEY_UNKNOWN || ui::IsKeyDown(scancode)))
        ui::SetTooltip("%s", text);
}

bool IconButton(const char* label)
{
    float size = ui::GetItemRectSize().y;
    return ui::Button(label, {size, size});
}

bool MaskSelector(unsigned int* mask)
{
    bool modified = false;
    auto style = ui::GetStyle();
    auto pos = ui::GetCursorPos();

    for (auto row = 0; row < 2; row++)
    {
        for (auto col = 0; col < 16; col++)
        {
            auto bitPosition = row * 16 + col;
            int bitMask = 1 << bitPosition;
            bool selected = (*mask & bitMask) != 0;
            if (selected)
            {
                ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_ButtonActive]);
                ui::PushStyleColor(ImGuiCol_ButtonHovered, style.Colors[ImGuiCol_ButtonActive]);
            }
            else
            {
                ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_Button]);
                ui::PushStyleColor(ImGuiCol_ButtonHovered, style.Colors[ImGuiCol_Button]);
            }

            ui::PushID(bitMask);
            if (ui::Button("", {8_dpx, 9_dpy}))
            {
                modified = true;
                *mask ^= bitMask;
            }
            if (ui::IsItemHovered())
                ui::SetTooltip("%d", bitPosition);
            ui::PopID();
            ui::SameLine(0, 0);
            ui::PopStyleColor(2);
        }
        ui::NewLine();
        if (row < 1)
            ui::SetCursorPos({pos.x, pos.y + 9_dpy});
    }

    return modified;
}

enum TransformResizeType
{
    RESIZE_NONE = 0,
    RESIZE_LEFT = 1,
    RESIZE_RIGHT = 2,
    RESIZE_TOP = 4,
    RESIZE_BOTTOM = 8,
    RESIZE_MOVE = 15,
};

}
/// Flag manipuation operators.
URHO3D_FLAGSET_EX(ImGui, TransformResizeType, TransformResizeTypeFlags);

namespace ImGui
{
/// Hashing function which enables use of enum type as a HashMap key.
inline unsigned MakeHash(const TransformResizeType& value) { return value; }

bool TransformRect(IntRect& inOut, TransformSelectorFlags flags)
{
    IntRect delta;
    return TransformRect(inOut, delta, flags);
}

bool TransformRect(Urho3D::IntRect& inOut, Urho3D::IntRect& delta, TransformSelectorFlags flags)
{
    struct State
    {
        /// A flag indicating type of resize action currently in progress
        TransformResizeTypeFlags resizing_ = RESIZE_NONE;
        /// A cache of system cursors
        HashMap<TransformResizeTypeFlags, SDL_Cursor*> cursors_;
        /// Default cursor shape
        SDL_Cursor* cursorArrow_;
        /// Flag indicating that this selector set cursor handle
        bool ownsCursor_ = false;

        State()
        {
            cursors_[RESIZE_MOVE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL);
            cursors_[RESIZE_LEFT] = cursors_[RESIZE_RIGHT] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE);
            cursors_[RESIZE_BOTTOM] = cursors_[RESIZE_TOP] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS);
            cursors_[RESIZE_TOP | RESIZE_LEFT] = cursors_[RESIZE_BOTTOM | RESIZE_RIGHT] = SDL_CreateSystemCursor(
                SDL_SYSTEM_CURSOR_SIZENWSE);
            cursors_[RESIZE_TOP | RESIZE_RIGHT] = cursors_[RESIZE_BOTTOM | RESIZE_LEFT] = SDL_CreateSystemCursor(
                SDL_SYSTEM_CURSOR_SIZENESW);
            cursorArrow_ = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
        }

        ~State()
        {
            SDL_FreeCursor(cursorArrow_);
            for (const auto& it : cursors_)
                SDL_FreeCursor(it.second_);
        }
    };

    Input* input = ui::GetSystemUI()->GetSubsystem<Input>();

    auto renderHandle = [&](IntVector2 screenPos, int wh) -> bool {
        IntRect rect(
            screenPos.x_ - wh / 2,
            screenPos.y_ - wh / 2,
            screenPos.x_ + wh / 2,
            screenPos.y_ + wh / 2
        );

        if (!(flags & TSF_HIDEHANDLES))
        {
            ui::GetWindowDrawList()->AddRectFilled(ToImGui(rect.Min()), ToImGui(rect.Max()),
                ui::GetColorU32(ToImGui(Color::RED)));
        }

        return rect.IsInside(input->GetMousePosition()) == INSIDE;
    };

    auto size = inOut.Size();
    auto handleSize = Max(Min(Min(size.x_ / 4, size.y_ / 4), 8), 2);
    bool modified = false;

    auto* s = ui::GetUIState<State>();
    auto id = ui::GetID(s);

    // Extend rect to cover resize handles that are sticking out of ui element boundaries.
    auto extendedRect = inOut + IntRect(-handleSize / 2, -handleSize / 2, handleSize / 2, handleSize / 2);
    ui::ItemSize(ToImGui(inOut));
    if (ui::ItemAdd(ToImGui(extendedRect), id))
    {
        TransformResizeTypeFlags resizing = RESIZE_NONE;
        if (renderHandle(inOut.Min() + size / 2, handleSize))
            resizing = RESIZE_MOVE;

        bool canResizeHorizontal = !(flags & TSF_NOHORIZONTAL);
        bool canResizeVertical = !(flags & TSF_NOVERTICAL);

        if (canResizeHorizontal && canResizeVertical)
        {
            if (renderHandle(inOut.Min(), handleSize))
                resizing = RESIZE_LEFT | RESIZE_TOP;
            if (renderHandle(inOut.Min() + IntVector2(0, size.y_), handleSize))
                resizing = RESIZE_LEFT | RESIZE_BOTTOM;
            if (renderHandle(inOut.Min() + IntVector2(size.x_, 0), handleSize))
                resizing = RESIZE_TOP | RESIZE_RIGHT;
            if (renderHandle(inOut.Max(), handleSize))
                resizing = RESIZE_BOTTOM | RESIZE_RIGHT;
        }

        if (canResizeHorizontal)
        {
            if (renderHandle(inOut.Min() + IntVector2(0, size.y_ / 2), handleSize))
                resizing = RESIZE_LEFT;
            if (renderHandle(inOut.Min() + IntVector2(size.x_, size.y_ / 2), handleSize))
                resizing = RESIZE_RIGHT;
        }

        if (canResizeVertical)
        {
            if (renderHandle(inOut.Min() + IntVector2(size.x_ / 2, 0), handleSize))
                resizing = RESIZE_TOP;
            if (renderHandle(inOut.Min() + IntVector2(size.x_ / 2, size.y_), handleSize))
                resizing = RESIZE_BOTTOM;
        }

        // Draw rect around selected element
        ui::GetWindowDrawList()->AddRect(ToImGui(inOut.Min()), ToImGui(inOut.Max()),
            ui::GetColorU32(ToImGui(Color::RED)));

        // Reset mouse cursor if we are not hovering any handle and are not resizing
        if (resizing == RESIZE_NONE && s->resizing_ == RESIZE_NONE && s->ownsCursor_)
        {
            SDL_SetCursor(s->cursorArrow_);
            s->ownsCursor_ = false;
        }

        // Prevent interaction when something else blocks inactive transform.
        if (s->resizing_ != RESIZE_NONE || (ui::IsItemHovered(ImGuiHoveredFlags_RectOnly) &&
            (!ui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow) || ui::IsWindowHovered())))
        {
            // Set mouse cursor if handle is hovered or if we are resizing
            if (resizing != RESIZE_NONE && !s->ownsCursor_)
            {
                SDL_SetCursor(s->cursors_[resizing]);
                s->ownsCursor_ = true;
            }

            // Begin resizing
            if (ui::IsMouseClicked(0))
                s->resizing_ = resizing;

            IntVector2 d = ToIntVector2(ui::GetIO().MouseDelta);
            if (s->resizing_ != RESIZE_NONE)
            {
                ui::SetActiveID(id, ui::GetCurrentWindow());
                if (!ui::IsMouseDown(0))
                    s->resizing_ = RESIZE_NONE;
                else if (d != IntVector2::ZERO)
                {
                    delta = IntRect::ZERO;

                    if (s->resizing_ == RESIZE_MOVE)
                    {
                        delta.left_ += d.x_;
                        delta.right_ += d.x_;
                        delta.top_ += d.y_;
                        delta.bottom_ += d.y_;
                        modified = true;
                    }
                    else
                    {
                        if (s->resizing_ & RESIZE_LEFT)
                        {
                            delta.left_ += d.x_;
                            modified = true;
                        }
                        else if (s->resizing_ & RESIZE_RIGHT)
                        {
                            delta.right_ += d.x_;
                            modified = true;
                        }

                        if (s->resizing_ & RESIZE_TOP)
                        {
                            delta.top_ += d.y_;
                            modified = true;
                        }
                        else if (s->resizing_ & RESIZE_BOTTOM)
                        {
                            delta.bottom_ += d.y_;
                            modified = true;
                        }
                    }
                }
            }
            else if (ui::IsItemActive())
                ui::SetActiveID(0, ui::GetCurrentWindow());

            if (modified)
                inOut += delta;
        }
        else if (ui::IsItemActive())
            ui::SetActiveID(0, ui::GetCurrentWindow());
    }
    return modified;
}

SystemUI* GetSystemUI()
{
    return static_cast<SystemUI*>(ui::GetIO().UserData);
}

bool EditorToolbarButton(const char* text, const char* tooltip, bool active)
{
    const auto& style = ui::GetStyle();
    if (active)
        ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_ButtonActive]);
    else
        ui::PushStyleColor(ImGuiCol_Button, style.Colors[ImGuiCol_Button]);
    bool result = ui::ToolbarButton(text);
    ui::PopStyleColor();
    ui::SameLine(0, 0);
    if (ui::IsItemHovered() && tooltip)
        ui::SetTooltip("%s", tooltip);
    return result;
}

void OpenTreeNode(ImGuiID id)
{
    auto& storage = ui::GetCurrentWindow()->DC.StateStorage;
    if (!storage->GetInt(id))
    {
        storage->SetInt(id, true);
        ui::TreePushRawID(id);
    }
}

}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2005, 2008 Apple Inc. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
 */

#include "config.h"
#include "core/editing/RemoveNodeCommand.h"

#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/dom/Node.h"
#include "wtf/Assertions.h"

namespace WebCore {

RemoveNodeCommand::RemoveNodeCommand(PassRefPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
    : SimpleEditCommand(node->document())
    , m_node(node)
    , m_shouldAssumeContentIsAlwaysEditable(shouldAssumeContentIsAlwaysEditable)
{
    ASSERT(m_node);
    ASSERT(m_node->parentNode());
}

void RemoveNodeCommand::doApply()
{
    ContainerNode* parent = m_node->parentNode();
    if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable
        && !parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) && parent->attached()))
        return;
    ASSERT(parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) || !parent->attached());

    m_parent = parent;
    m_refChild = m_node->nextSibling();

    m_node->remove(IGNORE_EXCEPTION);
}

void RemoveNodeCommand::doUnapply()
{
    RefPtr<ContainerNode> parent = m_parent.release();
    RefPtr<Node> refChild = m_refChild.release();
    if (!parent || !parent->rendererIsEditable())
        return;

    parent->insertBefore(m_node.get(), refChild.get(), IGNORE_EXCEPTION, DeprecatedAttachNow);
}

#ifndef NDEBUG
void RemoveNodeCommand::getNodesInCommand(HashSet<Node*>& nodes)
{
    addNodeAndDescendants(m_parent.get(), nodes);
    addNodeAndDescendants(m_refChild.get(), nodes);
    addNodeAndDescendants(m_node.get(), nodes);
}
#endif

}
<commit_msg>RemoveNodeCommand should attach lazily.<commit_after>/*
 * Copyright (C) 2005, 2008 Apple Inc. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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.
 */

#include "config.h"
#include "core/editing/RemoveNodeCommand.h"

#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "core/dom/Node.h"
#include "wtf/Assertions.h"

namespace WebCore {

RemoveNodeCommand::RemoveNodeCommand(PassRefPtr<Node> node, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAlwaysEditable)
    : SimpleEditCommand(node->document())
    , m_node(node)
    , m_shouldAssumeContentIsAlwaysEditable(shouldAssumeContentIsAlwaysEditable)
{
    ASSERT(m_node);
    ASSERT(m_node->parentNode());
}

void RemoveNodeCommand::doApply()
{
    ContainerNode* parent = m_node->parentNode();
    if (!parent || (m_shouldAssumeContentIsAlwaysEditable == DoNotAssumeContentIsAlwaysEditable
        && !parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) && parent->attached()))
        return;
    ASSERT(parent->isContentEditable(Node::UserSelectAllIsAlwaysNonEditable) || !parent->attached());

    m_parent = parent;
    m_refChild = m_node->nextSibling();

    m_node->remove(IGNORE_EXCEPTION);
}

void RemoveNodeCommand::doUnapply()
{
    RefPtr<ContainerNode> parent = m_parent.release();
    RefPtr<Node> refChild = m_refChild.release();
    if (!parent || !parent->rendererIsEditable())
        return;

    parent->insertBefore(m_node.get(), refChild.get(), IGNORE_EXCEPTION);
}

#ifndef NDEBUG
void RemoveNodeCommand::getNodesInCommand(HashSet<Node*>& nodes)
{
    addNodeAndDescendants(m_parent.get(), nodes);
    addNodeAndDescendants(m_refChild.get(), nodes);
    addNodeAndDescendants(m_node.get(), nodes);
}
#endif

}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// REQUIRES: diagnose-if-support
// UNSUPPORTED: c++98, c++03

// Libc++ only provides a defined primary template for std::hash in C++14 and
// newer.
// UNSUPPORTED: c++11

// <unordered_set>

// Test that we generate a reasonable diagnostic when the specified hash is
// not enabled.

#include <unordered_set>
#include <utility>

using VT = std::pair<int, int>;

struct BadHashNoCopy {
  BadHashNoCopy() = default;
  BadHashNoCopy(BadHashNoCopy const&) = delete;

  template <class T>
  size_t operator()(T const&) const { return 0; }
};

struct BadHashNoCall {

};

struct GoodHashNoDefault {
  explicit GoodHashNoDefault(void*) {}
  template <class T>
  size_t operator()(T const&) const { return 0; }
};

int main() {

  {
    using Set = std::unordered_set<VT>;
    Set s; // expected-error@__hash_table:* {{the specified hash does not meet the Hash requirements}}

  // FIXME: It would be great to suppress the below diagnostic all together.
  //        but for now it's sufficient that it appears last. However there is
  //        currently no way to test the order diagnostics are issued.
  // expected-error@memory:* {{call to implicitly-deleted default constructor of 'std::__1::hash<std::__1::pair<int, int> >'}}
  }
  {
    using Set = std::unordered_set<int, BadHashNoCopy>;
    Set s; // expected-error@__hash_table:* {{the specified hash does not meet the Hash requirements}}
  }
  {
    using Set = std::unordered_set<int, BadHashNoCall>;
    Set s; // expected-error@__hash_table:* {{the specified hash does not meet the Hash requirements}}
  }
  {
    using Set = std::unordered_set<int, GoodHashNoDefault>;
    Set s(/*bucketcount*/42, GoodHashNoDefault(nullptr));
  }
}
<commit_msg>Update tests -verify error messages after r300140.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// REQUIRES: diagnose-if-support
// UNSUPPORTED: c++98, c++03

// Libc++ only provides a defined primary template for std::hash in C++14 and
// newer.
// UNSUPPORTED: c++11

// <unordered_set>

// Test that we generate a reasonable diagnostic when the specified hash is
// not enabled.

#include <unordered_set>
#include <utility>

using VT = std::pair<int, int>;

struct BadHashNoCopy {
  BadHashNoCopy() = default;
  BadHashNoCopy(BadHashNoCopy const&) = delete;

  template <class T>
  size_t operator()(T const&) const { return 0; }
};

struct BadHashNoCall {

};

struct GoodHashNoDefault {
  explicit GoodHashNoDefault(void*) {}
  template <class T>
  size_t operator()(T const&) const { return 0; }
};

int main() {

  {
    using Set = std::unordered_set<VT>;
    Set s; // expected-error@__hash_table:* {{the specified hash does not meet the Hash requirements}}

  // FIXME: It would be great to suppress the below diagnostic all together.
  //        but for now it's sufficient that it appears last. However there is
  //        currently no way to test the order diagnostics are issued.
  // expected-error@memory:* {{call to implicitly-deleted default constructor of '__compressed_pair_elem}}
  }
  {
    using Set = std::unordered_set<int, BadHashNoCopy>;
    Set s; // expected-error@__hash_table:* {{the specified hash does not meet the Hash requirements}}
  }
  {
    using Set = std::unordered_set<int, BadHashNoCall>;
    Set s; // expected-error@__hash_table:* {{the specified hash does not meet the Hash requirements}}
  }
  {
    using Set = std::unordered_set<int, GoodHashNoDefault>;
    Set s(/*bucketcount*/42, GoodHashNoDefault(nullptr));
  }
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <istream>

// streamsize readsome(char_type* s, streamsize n);

#include <istream>
#include <cassert>

template <class CharT>
struct testbuf
    : public std::basic_streambuf<CharT>
{
    typedef std::basic_string<CharT> string_type;
    typedef std::basic_streambuf<CharT> base;
private:
    string_type str_;
public:

    testbuf() {}
    testbuf(const string_type& str)
        : str_(str)
    {
        base::setg(const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()) + str_.size());
    }

    CharT* eback() const {return base::eback();}
    CharT* gptr() const {return base::gptr();}
    CharT* egptr() const {return base::egptr();}
};

int main()
{
    {
        testbuf<char> sb(" 1234567890");
        std::istream is(&sb);
        char s[5];
        assert(is.readsome(s, 5) == 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::string(s, 5) == " 1234");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::string(s, 5) == "56789");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(is.gcount() == 1);
        assert(std::string(s, 1) == "0");
    }
    {
        testbuf<wchar_t> sb(L" 1234567890");
        std::wistream is(&sb);
        wchar_t s[5];
        assert(is.readsome(s, 5) == 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::wstring(s, 5) == L" 1234");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::wstring(s, 5) == L"56789");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(is.gcount() == 1);
        assert(std::wstring(s, 1) == L"0");
    }
}
<commit_msg>Test case for http://llvm.org/bugs/show_bug.cgi?id=14670.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <istream>

// streamsize readsome(char_type* s, streamsize n);

#include <istream>
#include <cassert>

template <class CharT>
struct testbuf
    : public std::basic_streambuf<CharT>
{
    typedef std::basic_string<CharT> string_type;
    typedef std::basic_streambuf<CharT> base;
private:
    string_type str_;
public:

    testbuf() {}
    testbuf(const string_type& str)
        : str_(str)
    {
        base::setg(const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()),
                   const_cast<CharT*>(str_.data()) + str_.size());
    }

    CharT* eback() const {return base::eback();}
    CharT* gptr() const {return base::gptr();}
    CharT* egptr() const {return base::egptr();}
};

int main()
{
    {
        testbuf<char> sb(" 1234567890");
        std::istream is(&sb);
        char s[5];
        assert(is.readsome(s, 5) == 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::string(s, 5) == " 1234");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::string(s, 5) == "56789");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(is.gcount() == 1);
        assert(std::string(s, 1) == "0");
        assert(is.readsome(s, 5) == 0);
    }
    {
        testbuf<wchar_t> sb(L" 1234567890");
        std::wistream is(&sb);
        wchar_t s[5];
        assert(is.readsome(s, 5) == 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::wstring(s, 5) == L" 1234");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(std::wstring(s, 5) == L"56789");
        assert(is.gcount() == 5);
        is.readsome(s, 5);
        assert(!is.eof());
        assert(!is.fail());
        assert(is.gcount() == 1);
        assert(std::wstring(s, 1) == L"0");
        assert(is.readsome(s, 5) == 0);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CONFIGURATION_TUNEBENCH_HPP
#define CONFIGURATION_TUNEBENCH_HPP

// Define the data types
typedef float inputDataType;
std::string inputDataName("float");
typedef float outputDataType;
std::string outputDataName("float");

// Magic value
const unsigned int magicValue = 42;

// MD
const float LJ1 = 1.5f;
const float LJ2 = 2.0f;

// Correlator
const unsigned int nrPolarizations = 2;

#endif // CONFIGURATION_TUNEBENCH_HPP

<commit_msg>Forgot to move one constant.<commit_after>// Copyright 2016 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CONFIGURATION_TUNEBENCH_HPP
#define CONFIGURATION_TUNEBENCH_HPP

// Define the data types
typedef float inputDataType;
std::string inputDataName("float");
typedef float outputDataType;
std::string outputDataName("float");

// Magic value
const unsigned int magicValue = 42;

// Triad
const unsigned int factor = 42;

// MD
const float LJ1 = 1.5f;
const float LJ2 = 2.0f;

// Correlator
const unsigned int nrPolarizations = 2;

#endif // CONFIGURATION_TUNEBENCH_HPP

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of the Willow Garage, Inc. 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.
 */
#pragma once
#include <ecto/tendril.hpp>
#include <ecto/spore.hpp>
#include <boost/thread.hpp>

#include <string>
#include <sstream>
#include <cstring>
#include <map>
#include <stdexcept>

namespace ecto
{
  /**
   * \brief The tendrils are a collection for the ecto::tendril class, addressable by a string key.
   */
  class ECTO_EXPORT tendrils : boost::noncopyable
  {
  public:

    typedef std::map<std::string, tendril::ptr> storage_type;

    typedef storage_type::iterator iterator;
    typedef storage_type::const_iterator const_iterator;
    typedef storage_type::value_type value_type;
    typedef storage_type::key_type key_type;
    typedef storage_type::size_type size_type;
    typedef storage_type::difference_type difference_type;
    typedef storage_type::key_compare key_compare;

    tendrils();

    iterator begin() { return storage.begin(); }
    const_iterator begin() const { return storage.begin(); }
    iterator end() { return storage.end(); }
    const_iterator end() const { return storage.end(); }

    iterator find(const std::string& name) { return storage.find(name); }
    const_iterator find(const std::string& name) const { return storage.find(name); }

    void clear() { storage.clear(); }

    size_type size() const { return storage.size(); }

    void erase(iterator pos) { storage.erase(pos); }
    void erase(const key_type& k) { storage.erase(k); }

    template <typename InputIterator>
    void
    insert(InputIterator first, InputIterator last)
    {
      storage.insert(first, last);
    }

    std::pair<iterator, bool> insert(const value_type &v)
    {
      return storage.insert(v);
    }

    key_compare key_comp() const { return storage.key_comp(); }

    /**
     * \brief Declare a tendril of a certain type, with only a name, no doc, or default values.
     * @tparam T the type of tendril to declare.
     * @param name The key for the tendril. Must be unique.
     * @return A typed holder for the tendril.
     */
    template<typename T>
    spore<T>
    declare(const std::string& name)
    {
      tendril::ptr t(make_tendril<T>());
      return declare(name, t);
    }

    /**
     * @see tendrils::declare
     * @param name @see tendrils::declare
     * @param doc The doc string for the tendril.
     * @return @see tendrils::declare
     */
    template<typename T>
    spore<T>
    declare(const std::string& name, const std::string& doc)
    {
      return declare<T>(name).set_doc(doc);
    }

    /**
     * @see tendrils::declare
     * @param name @see tendrils::declare
     * @param doc @see tendrils::declare
     * @param default_val A default value for the tendril.
     * @return @see tendrils::declare
     */
    template<typename T>
    spore<T>
    declare(const std::string& name, const std::string& doc, const T& default_val)
    {
      return declare<T>(name, doc).set_default_val(default_val);
    }

    /**
     * Runtime declare function.
     * @param name
     * @param t
     * @return
     */
    tendril::ptr
    declare(const std::string& name, tendril::ptr t);

    /**
     * \brief get the given type that is stored at the given key.  Will throw if there is a type mismatch.
     * @tparam T The compile time type to attempt to get from the tendrils.
     * @param name The key value
     * @return A const reference to the value, no copy is done.
     */
    /*
    template <typename T>
    const T&
    get(const std::string& name) const
    {
      try
      {
        const_iterator iter = storage.find(name);
        if (iter == end())
          doesnt_exist(name);
        return iter->second->get<T>();
      }catch(except::TypeMismatch& e)
      {
        e << std::string("  Hint : " ) + "'"+name+"' is of type: " + storage.at(name)->type_name();
        throw e;
      }
    }
    */

    /**
     * \brief get the given type that is stored at the given key.  Will throw if there is a type mismatch.
     * @tparam T The compile time type to attempt to get from the tendrils.
     * @param name The key value
     * @return A reference to the value, no copy is done.
     */
    template<typename T>
    T&
    get(const std::string& name) const
    {
      try
      {
        const_iterator iter = storage.find(name);
        if (iter == end())
          doesnt_exist(name);
        return iter->second->get<T>();
      } catch (except::TypeMismatch& e)
      {
        e << std::string("  Hint : ") + "'" + name + "' is of type: " + storage.at(name)->type_name();
        throw e;
      }
    }

    /**
     * \brief Grabs the tendril at the key.
     * @param name The key for the desired tendril.
     * @return A shared pointer to the tendril.
     * this throws if the key is not in the tendrils object
     */
    const tendril::ptr& operator[](const std::string& name) const;

    tendril::ptr& operator[](const std::string& name);

    /**
     * \brief Print the tendrils documentation string, in rst format.
     * @param out The stream to print to.
     * @param tendrils_name The name used as a label, for the tendrils.
     */
    void
    print_doc(std::ostream& out, const std::string& tendrils_name) const;

    typedef boost::shared_ptr<tendrils> ptr;
    typedef boost::shared_ptr<const tendrils> const_ptr;

  private:

    void doesnt_exist(const std::string& name) const;

    storage_type storage;

    mutable boost::mutex mtx;

    tendrils(const tendrils&);

  };
}
<commit_msg>Remove cruft from tendrils.hpp.<commit_after>/*
 * Copyright (c) 2011, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of the Willow Garage, Inc. 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.
 */
#pragma once
#include <ecto/tendril.hpp>
#include <ecto/spore.hpp>
#include <boost/thread.hpp>

#include <string>
#include <sstream>
#include <cstring>
#include <map>
#include <stdexcept>

namespace ecto
{
  /**
   * \brief The tendrils are a collection for the ecto::tendril class, addressable by a string key.
   */
  class ECTO_EXPORT tendrils : boost::noncopyable
  {
  public:

    typedef std::map<std::string, tendril::ptr> storage_type;

    typedef storage_type::iterator iterator;
    typedef storage_type::const_iterator const_iterator;
    typedef storage_type::value_type value_type;
    typedef storage_type::key_type key_type;
    typedef storage_type::size_type size_type;
    typedef storage_type::difference_type difference_type;
    typedef storage_type::key_compare key_compare;

    tendrils();

    iterator begin() { return storage.begin(); }
    const_iterator begin() const { return storage.begin(); }
    iterator end() { return storage.end(); }
    const_iterator end() const { return storage.end(); }

    iterator find(const std::string& name) { return storage.find(name); }
    const_iterator find(const std::string& name) const { return storage.find(name); }

    void clear() { storage.clear(); }

    size_type size() const { return storage.size(); }

    void erase(iterator pos) { storage.erase(pos); }
    void erase(const key_type& k) { storage.erase(k); }

    template <typename InputIterator>
    void
    insert(InputIterator first, InputIterator last)
    {
      storage.insert(first, last);
    }

    std::pair<iterator, bool> insert(const value_type &v)
    {
      return storage.insert(v);
    }

    key_compare key_comp() const { return storage.key_comp(); }

    /**
     * \brief Declare a tendril of a certain type, with only a name, no doc, or default values.
     * @tparam T the type of tendril to declare.
     * @param name The key for the tendril. Must be unique.
     * @return A typed holder for the tendril.
     */
    template<typename T>
    spore<T>
    declare(const std::string& name)
    {
      tendril::ptr t(make_tendril<T>());
      return declare(name, t);
    }

    /**
     * @see tendrils::declare
     * @param name @see tendrils::declare
     * @param doc The doc string for the tendril.
     * @return @see tendrils::declare
     */
    template<typename T>
    spore<T>
    declare(const std::string& name, const std::string& doc)
    {
      return declare<T>(name).set_doc(doc);
    }

    /**
     * @see tendrils::declare
     * @param name @see tendrils::declare
     * @param doc @see tendrils::declare
     * @param default_val A default value for the tendril.
     * @return @see tendrils::declare
     */
    template<typename T>
    spore<T>
    declare(const std::string& name, const std::string& doc, const T& default_val)
    {
      return declare<T>(name, doc).set_default_val(default_val);
    }

    /**
     * Runtime declare function.
     * @param name
     * @param t
     * @return
     */
    tendril::ptr
    declare(const std::string& name, tendril::ptr t);

    /**
     * \brief get the given type that is stored at the given key.  Will throw if there is a type mismatch.
     * @tparam T The compile time type to attempt to get from the tendrils.
     * @param name The key value
     * @return A reference to the value, no copy is done.
     */
    template<typename T>
    T&
    get(const std::string& name) const
    {
      try
      {
        const_iterator iter = storage.find(name);
        if (iter == end())
          doesnt_exist(name);
        return iter->second->get<T>();
      } catch (except::TypeMismatch& e)
      {
        e << std::string("  Hint : ") + "'" + name + "' is of type: " + storage.at(name)->type_name();
        throw e;
      }
    }

    /**
     * \brief Grabs the tendril at the key.
     * @param name The key for the desired tendril.
     * @return A shared pointer to the tendril.
     * this throws if the key is not in the tendrils object
     */
    const tendril::ptr& operator[](const std::string& name) const;

    tendril::ptr& operator[](const std::string& name);

    /**
     * \brief Print the tendrils documentation string, in rst format.
     * @param out The stream to print to.
     * @param tendrils_name The name used as a label, for the tendrils.
     */
    void
    print_doc(std::ostream& out, const std::string& tendrils_name) const;

    typedef boost::shared_ptr<tendrils> ptr;
    typedef boost::shared_ptr<const tendrils> const_ptr;

  private:

    void doesnt_exist(const std::string& name) const;

    storage_type storage;

    mutable boost::mutex mtx;

    tendrils(const tendrils&);

  };
}
<|endoftext|>


<commit_before>#include "ImageWriter.h"

uint32 ImageWriter::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {
	uint32 bytesPerRow = GetWidth() * 4;
	uint32 byteLocation = y * bytesPerRow + x*4 + ch;
	return m_PixelData[byteLocation];
}
<commit_msg>Make sure that we assume pixels are in block stream order when accessing.<commit_after>#include "ImageWriter.h"

uint32 ImageWriter::GetChannelForPixel(uint32 x, uint32 y, uint32 ch) {

  // Assume pixels are in block stream order, hence we would need to first find
  // the block that contains pixel (x, y) and then find the byte location for it.

  const uint32 blocksPerRow = GetWidth() / 4;
  const uint32 blockIdxX = x / 4;
  const uint32 blockIdxY = y / 4;
  const uint32 blockIdx = blockIdxY * blocksPerRow + blockIdxX;

  // Now we find the offset in the block
  const uint32 blockOffsetX = x % 4;
  const uint32 blockOffsetY = y % 4;
  const uint32 pixelOffset = blockOffsetY * 4 + blockOffsetX;

  // There are 16 pixels per block and bytes per pixel...
  uint32 dataOffset = blockIdx * 4 * 16;
  dataOffset += 4 * pixelOffset;
  dataOffset += ch;

  return m_PixelData[dataOffset];
}
<|endoftext|>