<commit_before>// FIXME - Something hangs if PKTCTRL0==4 (fixed length packets) when
// variable-length packets are in use.

#include <stdio.h>
#include <stdexcept>
#include <boost/format.hpp>

#include <QMutexLocker>

#include <Utils.hpp>
#include "USBRadio.hpp"
#include "cc1101.h"
#include "radio_config.h"

using namespace std;
using namespace boost;
using namespace Packet;

// Timeout for control transfers, in milliseconds
static const int Control_Timeout = 1000;

USBRadio::USBRadio() {
    _sequence = 0;
    _printedError = false;
    _device = nullptr;
    _usb_context = nullptr;
    libusb_init(&_usb_context);

    for (int i = 0; i < NumRXTransfers; ++i) {
        _rxTransfers[i] = libusb_alloc_transfer(0);
    }
}

USBRadio::~USBRadio() {
    if (_device) {
        libusb_close(_device);
    }

    for (int i = 0; i < NumRXTransfers; ++i) {
        libusb_free_transfer(_rxTransfers[i]);
    }

    libusb_exit(_usb_context);
}

bool USBRadio::open() {
    libusb_device** devices = nullptr;
    ssize_t numDevices = libusb_get_device_list(_usb_context, &devices);

    if (numDevices < 0) {
        fprintf(stderr, "libusb_get_device_list failed\n");
        return false;
    }

    int numRadios = 0;
    for (int i = 0; i < numDevices; ++i) {
        struct libusb_device_descriptor desc;
        int err = libusb_get_device_descriptor(devices[i], &desc);
        if (err == 0 && desc.idVendor == 0x3141 && desc.idProduct == 0x0004) {
            ++numRadios;
            int err = libusb_open(devices[i], &_device);
            if (err == 0) {
                break;
            }
        }
    }

    libusb_free_device_list(devices, 1);

    if (!numRadios) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: No radio is connected\n");
            _printedError = true;
        }
        return false;
    }

    if (!_device) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: All radios are in use\n");
            _printedError = true;
        }
        return false;
    }

    if (libusb_set_configuration(_device, 1)) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: Can't set configuration\n");
            _printedError = true;
        }
        return false;
    }

    if (libusb_claim_interface(_device, 0)) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: Can't claim interface\n");
            _printedError = true;
        }
        return false;
    }

    configure();

    // Start the receive transfers
    for (int i = 0; i < NumRXTransfers; ++i) {
        // Populate the required libusb_transfer fields for a bulk transfer.
        libusb_fill_bulk_transfer(
            _rxTransfers[i],  // the transfer to populate
            _device,  // handle of the device that will handle the transfer
            LIBUSB_ENDPOINT_IN |
                2,  // address of the endpoint where this transfer will be sent
            _rxBuffers[i],     // data buffer
            Reverse_Size + 2,  // length of data buffer
            rxCompleted,       // callback function to be invoked on transfer
                               // completion
            this,              // user data to pass to callback function
            0);                // timeout for the transfer in milliseconds
        libusb_submit_transfer(_rxTransfers[i]);
    }

    _printedError = false;

    return true;
}

void USBRadio::rxCompleted(libusb_transfer* transfer) {
    USBRadio* radio = (USBRadio*)transfer->user_data;

    if (transfer->status == LIBUSB_TRANSFER_COMPLETED &&
        transfer->actual_length == Reverse_Size + 2) {
        // Parse the packet and add to the list of RadioRx's
        radio->handleRxData(transfer->buffer);
    }

    // Restart the transfer
    libusb_submit_transfer(transfer);
}

void USBRadio::command(uint8_t cmd) {
    if (libusb_control_transfer(_device,
                                LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR,
                                2, 0, cmd, nullptr, 0, Control_Timeout)) {
        throw runtime_error("USBRadio::command control write failed");
    }
}

void USBRadio::write(uint8_t reg, uint8_t value) {
    if (libusb_control_transfer(_device,
                                LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR,
                                1, value, reg, nullptr, 0, Control_Timeout)) {
        throw runtime_error("USBRadio::write control write failed");
    }
}

uint8_t USBRadio::read(uint8_t reg) {
    uint8_t value = 0;
    if (libusb_control_transfer(_device,
                                LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR,
                                3, 0, reg, &value, 1, Control_Timeout)) {
        throw runtime_error("USBRadio::read control write failed");
    }

    return value;
}

void USBRadio::configure() {
    auto_calibrate(false);

    command(SIDLE);
    command(SFTX);
    command(SFRX);

    // Write configuration.
    // This is mainly for frequency, bit rate, and packetization.
    for (unsigned int i = 0; i < sizeof(cc1101_regs); i += 2) {
        write(cc1101_regs[i], cc1101_regs[i + 1]);
    }

    write(CHANNR, _channel);

    auto_calibrate(true);
}

void USBRadio::auto_calibrate(bool enable) {
    int flag = enable ? 1 : 0;
    assert(libusb_control_transfer(
               _device, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR, 4,
               flag, 0, nullptr, 0, Control_Timeout) == 0);
}

bool USBRadio::isOpen() const { return _device; }

void USBRadio::send(Packet::RadioTx& packet) {
    QMutexLocker lock(&_mutex);
    if (!_device) {
        if (!open()) {
            return;
        }
    }

    uint8_t forward_packet[Forward_Size];

    // Build a forward packet
    forward_packet[0] = _sequence;

    // Unit conversions
    static const float Seconds_Per_Cycle = 0.005f;
    static const float Meters_Per_Tick = 0.026f * 2 * M_PI / 6480.0f;
    static const float Radians_Per_Tick = 0.026f * M_PI / (0.0812f * 3240.0f);

    int offset = 1;
    int slot;
    for (slot = 0; slot < 6 && slot < packet.robots_size();
         ++slot) {
        const Packet::Control& robot =
            packet.robots(slot).control();
        int robot_id = packet.robots(slot).uid();

        float bodyVelX =
            robot.xvelocity() * Seconds_Per_Cycle / Meters_Per_Tick / sqrtf(2);
        float bodyVelY =
            robot.yvelocity() * Seconds_Per_Cycle / Meters_Per_Tick / sqrtf(2);
        float bodyVelW =
            robot.avelocity() * Seconds_Per_Cycle / Radians_Per_Tick;

        int outX = clamp((int)roundf(bodyVelX), -511, 511);
        int outY = clamp((int)roundf(bodyVelY), -511, 511);
        int outW = clamp((int)roundf(bodyVelW), -511, 511);

        uint8_t kick =
            static_cast<uint8_t>(robot.shootmode() == Packet::Control::KICK);
        uint8_t dribbler =
            max(0, min(255, static_cast<uint16_t>(robot.dvelocity()) * 2));

        forward_packet[offset++] = outX & 0xff;
        forward_packet[offset++] = outY & 0xff;
        forward_packet[offset++] = outW & 0xff;
        forward_packet[offset++] = ((outX & 0x300) >> 8) |
                                   ((outY & 0x300) >> 6) |
                                   ((outW & 0x300) >> 4);

        forward_packet[offset++] = (dribbler & 0xf0) | (robot_id & 0x0f);
        forward_packet[offset++] = kick;
        forward_packet[offset++] =
            (robot.shootmode() == Packet::Control::CHIP) |
            ((robot.triggermode() == Packet::Control::IMMEDIATE) << 1) |
            (robot.song() << 2) | (0 /*robot.anthem()*/ << 3);
        forward_packet[offset++] = 10;  // robot.accel();
        forward_packet[offset++] = 10;  // robot.decel();
    }

    // Unused slots
    for (; slot < 6; ++slot) {
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0x0f;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
    }

    // Send the forward packet
    int sent = 0;
    if (libusb_bulk_transfer(_device, LIBUSB_ENDPOINT_OUT | 1, forward_packet,
                             sizeof(forward_packet), &sent, Control_Timeout) ||
        sent != sizeof(forward_packet)) {
        fprintf(stderr, "USBRadio: Bulk write failed\n");
        libusb_close(_device);
        _device = nullptr;
    }

    _sequence = (_sequence + 1) & 7;
}

void USBRadio::receive() {
    QMutexLocker lock(&_mutex);

    if (!_device) {
        if (!open()) {
            return;
        }
    }

    // Handle USB events.  This will call callbacks.
    struct timeval tv = {0, 0};
    libusb_handle_events_timeout(_usb_context, &tv);
}

void USBRadio::handleRxData(uint8_t* buf) {
    RJ::Time rx_time = RJ::timestamp();

    _reversePackets.push_back(RadioRx());
    RadioRx& packet = _reversePackets.back();

    packet.set_timestamp(rx_time);
    packet.set_sequence((buf[0] >> 4) & 7);
    packet.set_robot_id(buf[0] & 0x0f);
    packet.set_rssi((int8_t)buf[1] / 2.0 - 74);
    packet.set_battery(buf[2] / 10.0f);
    packet.set_kicker_status(buf[3]);

    // Drive motor status
    for (int i = 0; i < 4; ++i) {
        packet.add_motor_status(MotorStatus((buf[4] >> (i * 2)) & 3));
    }

    // Dribbler status
    packet.add_motor_status(MotorStatus(buf[5] & 3));

    // Hardware version
    if (buf[5] & (1 << 4)) {
        packet.set_hardware_version(RJ2008);
    } else {
        packet.set_hardware_version(RJ2011);
    }

    packet.set_ball_sense_status(BallSenseStatus((buf[5] >> 2) & 3));
    packet.set_kicker_voltage(buf[6]);

#if 0
	// Encoders
	for (int i = 0; i < 4; ++i)
	{
		int high = (buf[10] >> (i * 2)) & 3;
		int16_t value = buf[6 + i] | (high << 8);
		if (high & 2)
		{
			value |= 0xfc00;
		}
		packet.add_encoders(value);
	}
#endif

#if 0
	if (buf[5] & (1 << 5))
	{
		// Quaternion
		int16_t q0 = buf[7] | (buf[8] << 8);
		int16_t q1 = buf[9] | (buf[10] << 8);
		int16_t q2 = buf[11] | (buf[12] << 8);
		int16_t q3 = buf[13] | (buf[14] << 8);
		packet.mutable_quaternion()->set_q0(q0 / 16384.0);
		packet.mutable_quaternion()->set_q1(q1 / 16384.0);
		packet.mutable_quaternion()->set_q2(q2 / 16384.0);
		packet.mutable_quaternion()->set_q3(q3 / 16384.0);
	}
#endif
}

void USBRadio::channel(int n) {
    QMutexLocker lock(&_mutex);

    if (_device) {
        auto_calibrate(false);

        write(CHANNR, n);

        command(SIDLE);
        command(SRX);

        auto_calibrate(true);
    }

    Radio::channel(n);
}
<commit_msg>commented accel/decel<commit_after>// FIXME - Something hangs if PKTCTRL0==4 (fixed length packets) when
// variable-length packets are in use.

#include <stdio.h>
#include <stdexcept>
#include <boost/format.hpp>

#include <QMutexLocker>

#include <Utils.hpp>
#include "USBRadio.hpp"
#include "cc1101.h"
#include "radio_config.h"

using namespace std;
using namespace boost;
using namespace Packet;

// Timeout for control transfers, in milliseconds
static const int Control_Timeout = 1000;

USBRadio::USBRadio() {
    _sequence = 0;
    _printedError = false;
    _device = nullptr;
    _usb_context = nullptr;
    libusb_init(&_usb_context);

    for (int i = 0; i < NumRXTransfers; ++i) {
        _rxTransfers[i] = libusb_alloc_transfer(0);
    }
}

USBRadio::~USBRadio() {
    if (_device) {
        libusb_close(_device);
    }

    for (int i = 0; i < NumRXTransfers; ++i) {
        libusb_free_transfer(_rxTransfers[i]);
    }

    libusb_exit(_usb_context);
}

bool USBRadio::open() {
    libusb_device** devices = nullptr;
    ssize_t numDevices = libusb_get_device_list(_usb_context, &devices);

    if (numDevices < 0) {
        fprintf(stderr, "libusb_get_device_list failed\n");
        return false;
    }

    int numRadios = 0;
    for (int i = 0; i < numDevices; ++i) {
        struct libusb_device_descriptor desc;
        int err = libusb_get_device_descriptor(devices[i], &desc);
        if (err == 0 && desc.idVendor == 0x3141 && desc.idProduct == 0x0004) {
            ++numRadios;
            int err = libusb_open(devices[i], &_device);
            if (err == 0) {
                break;
            }
        }
    }

    libusb_free_device_list(devices, 1);

    if (!numRadios) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: No radio is connected\n");
            _printedError = true;
        }
        return false;
    }

    if (!_device) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: All radios are in use\n");
            _printedError = true;
        }
        return false;
    }

    if (libusb_set_configuration(_device, 1)) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: Can't set configuration\n");
            _printedError = true;
        }
        return false;
    }

    if (libusb_claim_interface(_device, 0)) {
        if (!_printedError) {
            fprintf(stderr, "USBRadio: Can't claim interface\n");
            _printedError = true;
        }
        return false;
    }

    configure();

    // Start the receive transfers
    for (int i = 0; i < NumRXTransfers; ++i) {
        // Populate the required libusb_transfer fields for a bulk transfer.
        libusb_fill_bulk_transfer(
            _rxTransfers[i],  // the transfer to populate
            _device,  // handle of the device that will handle the transfer
            LIBUSB_ENDPOINT_IN |
                2,  // address of the endpoint where this transfer will be sent
            _rxBuffers[i],     // data buffer
            Reverse_Size + 2,  // length of data buffer
            rxCompleted,       // callback function to be invoked on transfer
                               // completion
            this,              // user data to pass to callback function
            0);                // timeout for the transfer in milliseconds
        libusb_submit_transfer(_rxTransfers[i]);
    }

    _printedError = false;

    return true;
}

void USBRadio::rxCompleted(libusb_transfer* transfer) {
    USBRadio* radio = (USBRadio*)transfer->user_data;

    if (transfer->status == LIBUSB_TRANSFER_COMPLETED &&
        transfer->actual_length == Reverse_Size + 2) {
        // Parse the packet and add to the list of RadioRx's
        radio->handleRxData(transfer->buffer);
    }

    // Restart the transfer
    libusb_submit_transfer(transfer);
}

void USBRadio::command(uint8_t cmd) {
    if (libusb_control_transfer(_device,
                                LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR,
                                2, 0, cmd, nullptr, 0, Control_Timeout)) {
        throw runtime_error("USBRadio::command control write failed");
    }
}

void USBRadio::write(uint8_t reg, uint8_t value) {
    if (libusb_control_transfer(_device,
                                LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR,
                                1, value, reg, nullptr, 0, Control_Timeout)) {
        throw runtime_error("USBRadio::write control write failed");
    }
}

uint8_t USBRadio::read(uint8_t reg) {
    uint8_t value = 0;
    if (libusb_control_transfer(_device,
                                LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR,
                                3, 0, reg, &value, 1, Control_Timeout)) {
        throw runtime_error("USBRadio::read control write failed");
    }

    return value;
}

void USBRadio::configure() {
    auto_calibrate(false);

    command(SIDLE);
    command(SFTX);
    command(SFRX);

    // Write configuration.
    // This is mainly for frequency, bit rate, and packetization.
    for (unsigned int i = 0; i < sizeof(cc1101_regs); i += 2) {
        write(cc1101_regs[i], cc1101_regs[i + 1]);
    }

    write(CHANNR, _channel);

    auto_calibrate(true);
}

void USBRadio::auto_calibrate(bool enable) {
    int flag = enable ? 1 : 0;
    assert(libusb_control_transfer(
               _device, LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR, 4,
               flag, 0, nullptr, 0, Control_Timeout) == 0);
}

bool USBRadio::isOpen() const { return _device; }

void USBRadio::send(Packet::RadioTx& packet) {
    QMutexLocker lock(&_mutex);
    if (!_device) {
        if (!open()) {
            return;
        }
    }

    uint8_t forward_packet[Forward_Size];

    // Build a forward packet
    forward_packet[0] = _sequence;

    // Unit conversions
    static const float Seconds_Per_Cycle = 0.005f;
    static const float Meters_Per_Tick = 0.026f * 2 * M_PI / 6480.0f;
    static const float Radians_Per_Tick = 0.026f * M_PI / (0.0812f * 3240.0f);

    int offset = 1;
    int slot;
    for (slot = 0; slot < 6 && slot < packet.robots_size();
         ++slot) {
        const Packet::Control& robot =
            packet.robots(slot).control();
        int robot_id = packet.robots(slot).uid();

        float bodyVelX =
            robot.xvelocity() * Seconds_Per_Cycle / Meters_Per_Tick / sqrtf(2);
        float bodyVelY =
            robot.yvelocity() * Seconds_Per_Cycle / Meters_Per_Tick / sqrtf(2);
        float bodyVelW =
            robot.avelocity() * Seconds_Per_Cycle / Radians_Per_Tick;

        int outX = clamp((int)roundf(bodyVelX), -511, 511);
        int outY = clamp((int)roundf(bodyVelY), -511, 511);
        int outW = clamp((int)roundf(bodyVelW), -511, 511);

        uint8_t kick =
            static_cast<uint8_t>(robot.shootmode() == Packet::Control::KICK);
        uint8_t dribbler =
            max(0, min(255, static_cast<uint16_t>(robot.dvelocity()) * 2));

        forward_packet[offset++] = outX & 0xff;
        forward_packet[offset++] = outY & 0xff;
        forward_packet[offset++] = outW & 0xff;
        forward_packet[offset++] = ((outX & 0x300) >> 8) |
                                   ((outY & 0x300) >> 6) |
                                   ((outW & 0x300) >> 4);

        forward_packet[offset++] = (dribbler & 0xf0) | (robot_id & 0x0f);
        forward_packet[offset++] = kick;
        forward_packet[offset++] =
            (robot.shootmode() == Packet::Control::CHIP) |
            ((robot.triggermode() == Packet::Control::IMMEDIATE) << 1) |
            (robot.song() << 2) | (0 /*robot.anthem()*/ << 3);
        // TODO remove, no longer used
        forward_packet[offset++] = 10;  // robot.accel();
        forward_packet[offset++] = 10;  // robot.decel();
    }

    // Unused slots
    for (; slot < 6; ++slot) {
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0x0f;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
        forward_packet[offset++] = 0;
    }

    // Send the forward packet
    int sent = 0;
    if (libusb_bulk_transfer(_device, LIBUSB_ENDPOINT_OUT | 1, forward_packet,
                             sizeof(forward_packet), &sent, Control_Timeout) ||
        sent != sizeof(forward_packet)) {
        fprintf(stderr, "USBRadio: Bulk write failed\n");
        libusb_close(_device);
        _device = nullptr;
    }

    _sequence = (_sequence + 1) & 7;
}

void USBRadio::receive() {
    QMutexLocker lock(&_mutex);

    if (!_device) {
        if (!open()) {
            return;
        }
    }

    // Handle USB events.  This will call callbacks.
    struct timeval tv = {0, 0};
    libusb_handle_events_timeout(_usb_context, &tv);
}

void USBRadio::handleRxData(uint8_t* buf) {
    RJ::Time rx_time = RJ::timestamp();

    _reversePackets.push_back(RadioRx());
    RadioRx& packet = _reversePackets.back();

    packet.set_timestamp(rx_time);
    packet.set_sequence((buf[0] >> 4) & 7);
    packet.set_robot_id(buf[0] & 0x0f);
    packet.set_rssi((int8_t)buf[1] / 2.0 - 74);
    packet.set_battery(buf[2] / 10.0f);
    packet.set_kicker_status(buf[3]);

    // Drive motor status
    for (int i = 0; i < 4; ++i) {
        packet.add_motor_status(MotorStatus((buf[4] >> (i * 2)) & 3));
    }

    // Dribbler status
    packet.add_motor_status(MotorStatus(buf[5] & 3));

    // Hardware version
    if (buf[5] & (1 << 4)) {
        packet.set_hardware_version(RJ2008);
    } else {
        packet.set_hardware_version(RJ2011);
    }

    packet.set_ball_sense_status(BallSenseStatus((buf[5] >> 2) & 3));
    packet.set_kicker_voltage(buf[6]);

#if 0
	// Encoders
	for (int i = 0; i < 4; ++i)
	{
		int high = (buf[10] >> (i * 2)) & 3;
		int16_t value = buf[6 + i] | (high << 8);
		if (high & 2)
		{
			value |= 0xfc00;
		}
		packet.add_encoders(value);
	}
#endif

#if 0
	if (buf[5] & (1 << 5))
	{
		// Quaternion
		int16_t q0 = buf[7] | (buf[8] << 8);
		int16_t q1 = buf[9] | (buf[10] << 8);
		int16_t q2 = buf[11] | (buf[12] << 8);
		int16_t q3 = buf[13] | (buf[14] << 8);
		packet.mutable_quaternion()->set_q0(q0 / 16384.0);
		packet.mutable_quaternion()->set_q1(q1 / 16384.0);
		packet.mutable_quaternion()->set_q2(q2 / 16384.0);
		packet.mutable_quaternion()->set_q3(q3 / 16384.0);
	}
#endif
}

void USBRadio::channel(int n) {
    QMutexLocker lock(&_mutex);

    if (_device) {
        auto_calibrate(false);

        write(CHANNR, n);

        command(SIDLE);
        command(SRX);

        auto_calibrate(true);
    }

    Radio::channel(n);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: urihelper.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-01-11 13:10:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SVTOOLS_URIHELPER_HXX
#define SVTOOLS_URIHELPER_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include "com/sun/star/uno/Reference.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif

#ifndef _RTL_TEXTENC_H
#include <rtl/textenc.h>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif
#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _URLOBJ_HXX
#include <tools/urlobj.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace uno { class XComponentContext; }
    namespace uri { class XUriReference; }
} } }
namespace rtl { class OUString; }
class ByteString;
class CharClass;
class UniString;

//============================================================================
namespace URIHelper {

UniString
SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
             ByteString const & rTheRelURIRef,
             Link const & rMaybeFileHdl = Link(),
             bool bCheckFileExists = true,
             bool bIgnoreFragment = false,
             INetURLObject::EncodeMechanism eEncodeMechanism
                 = INetURLObject::WAS_ENCODED,
             INetURLObject::DecodeMechanism eDecodeMechanism
                 = INetURLObject::DECODE_TO_IURI,
             rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8,
             bool bRelativeNonURIs = false,
             INetURLObject::FSysStyle eStyle = INetURLObject::FSYS_DETECT);

UniString
SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
             UniString const & rTheRelURIRef,
             Link const & rMaybeFileHdl = Link(),
             bool bCheckFileExists = true,
             bool bIgnoreFragment = false,
             INetURLObject::EncodeMechanism eEncodeMechanism
                 = INetURLObject::WAS_ENCODED,
             INetURLObject::DecodeMechanism eDecodeMechanism
                 = INetURLObject::DECODE_TO_IURI,
             rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8,
             bool bRelativeNonURIs = false,
             INetURLObject::FSysStyle eStyle = INetURLObject::FSYS_DETECT);

//============================================================================
void SetMaybeFileHdl(Link const & rTheMaybeFileHdl);

//============================================================================
Link GetMaybeFileHdl();

/**
   Converts a URI reference to a relative one, ignoring certain differences (for
   example, treating file URLs for case-ignoring file systems
   case-insensitively).

   @param context a component context; must not be null

   @param baseUriReference a base URI reference

   @param uriReference a URI reference

   @return a URI reference representing the given uriReference relative to the
   given baseUriReference; if the given baseUriReference is not an absolute,
   hierarchical URI reference, or the given uriReference is not a valid URI
   reference, null is returned

   @exception std::bad_alloc if an out-of-memory condition occurs

   @exception com::sun::star::uno::RuntimeException if any error occurs
 */
com::sun::star::uno::Reference< com::sun::star::uri::XUriReference >
normalizedMakeRelative(
    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
    const & context,
    rtl::OUString const & baseUriReference, rtl::OUString const & uriReference);

/**
   A variant of normalizedMakeRelative with a simplified interface.

   Internally calls normalizedMakeRelative with the default component context.

   @param baseUriReference a base URI reference, passed to
   normalizedMakeRelative

   @param uriReference a URI reference, passed to normalizedMakeRelative

   @return if the XUriReference returnd by normalizedMakeRelative is empty,
   uriReference is returned unmodified; otherwise, the result of calling
   XUriReference::getUriReference on the XUriReference returnd by
   normalizedMakeRelative is returned

   @exception std::bad_alloc if an out-of-memory condition occurs

   @exception com::sun::star::uno::RuntimeException if any error occurs

   @deprecated
   No code should rely on the default component context.
*/
rtl::OUString simpleNormalizedMakeRelative(
    rtl::OUString const & baseUriReference, rtl::OUString const & uriReference);

//============================================================================
UniString
FindFirstURLInText(UniString const & rText,
                   xub_StrLen & rBegin,
                   xub_StrLen & rEnd,
                   CharClass const & rCharClass,
                   INetURLObject::EncodeMechanism eMechanism
                       = INetURLObject::WAS_ENCODED,
                   rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8,
                   INetURLObject::FSysStyle eStyle
                       = INetURLObject::FSYS_DETECT);

//============================================================================
/** Remove any password component from both absolute and relative URLs.

    @ATT  The current implementation will not remove a password from a
    relative URL that has an authority component (e.g., the password is not
    removed from the relative ftp URL <//user:password@domain/path>).  But
    since our functions to translate between absolute and relative URLs never
    produce relative URLs with authority components, this is no real problem.

    @ATT  For relative URLs (or anything not recognized as an absolute URI),
    the current implementation will return the input unmodified, not applying
    any translations implied by the encode/decode parameters.

    @param rURI  An absolute or relative URI reference.

    @param eEncodeMechanism  See the general discussion for INetURLObject set-
    methods.

    @param eDecodeMechanism  See the general discussion for INetURLObject get-
    methods.

    @param eCharset  See the general discussion for INetURLObject get- and
    set-methods.

    @return  The input URI with any password component removed.
 */
UniString
removePassword(UniString const & rURI,
               INetURLObject::EncodeMechanism eEncodeMechanism
                   = INetURLObject::WAS_ENCODED,
               INetURLObject::DecodeMechanism eDecodeMechanism
                   = INetURLObject::DECODE_TO_IURI,
               rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8);

//============================================================================
/** Query the notational conventions used in the file system provided by some
    file content provider.

    @param rFileUrl  This file URL determines which file content provider is
    used to query the desired information.  (The UCB's usual mapping from URLs
    to content providers is used.)

    @param bAddConvenienceStyles  If true, the return value contains not only
    the style bit corresponding to the queried content provider's conventions,
    but may also contain additional style bits that make using this function
    more convenient in certain situations.  Currently, the effect is that
    FSYS_UNX is extended with FSYS_VOS, and both FSYS_DOS and FSYS_MAC are
    extended with FSYS_VOS and FSYS_UNX (i.e., the---unambiguous---detection
    of VOS style and Unix style file system paths is always enabled); also, in
    case the content provider's conventions cannot be determined, FSYS_DETECT
    is returned instead of FSysStyle(0).

    @return  The style bit corresponding to the queried content provider's
    conventions, or FSysStyle(0) if these cannot be determined.
 */
INetURLObject::FSysStyle queryFSysStyle(UniString const & rFileUrl,
                                        bool bAddConvenienceStyles = true)
    throw (com::sun::star::uno::RuntimeException);

}

#endif // SVTOOLS_URIHELPER_HXX
<commit_msg>INTEGRATION: CWS fwkpostbeta1 (1.3.42); FILE MERGED 2005/02/14 09:42:39 sb 1.3.42.1: #119209# Added documentation about potential problems.<commit_after>/*************************************************************************
 *
 *  $RCSfile: urihelper.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: kz $ $Date: 2005-03-21 13:30:20 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SVTOOLS_URIHELPER_HXX
#define SVTOOLS_URIHELPER_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include "com/sun/star/uno/Reference.hxx"
#endif
#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif

#ifndef _RTL_TEXTENC_H
#include <rtl/textenc.h>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif
#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _URLOBJ_HXX
#include <tools/urlobj.hxx>
#endif

namespace com { namespace sun { namespace star {
    namespace uno { class XComponentContext; }
    namespace uri { class XUriReference; }
} } }
namespace rtl { class OUString; }
class ByteString;
class CharClass;
class UniString;

//============================================================================
namespace URIHelper {

/**
   @ATT
   Calling this function with defaulted arguments rMaybeFileHdl = Link() and
   bCheckFileExists = true often leads to results that are not intended:
   Whenever the given rTheBaseURIRef is a file URL, the given rTheRelURIRef is
   relative, and rTheRelURIRef could also be smart-parsed as a non-file URL
   (e.g., the relative URL "foo/bar" can be smart-parsed as "http://foo/bar"),
   then SmartRel2Abs called with rMaybeFileHdl = Link() and bCheckFileExists =
   true returns the non-file URL interpretation.  To avoid this, either pass
   some non-null rMaybeFileHdl if you want to check generated file URLs for
   existence (see URIHelper::GetMaybeFileHdl), or use bCheckFileExists = false
   if you want to generate file URLs without checking for their existence.
*/
UniString
SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
             ByteString const & rTheRelURIRef,
             Link const & rMaybeFileHdl = Link(),
             bool bCheckFileExists = true,
             bool bIgnoreFragment = false,
             INetURLObject::EncodeMechanism eEncodeMechanism
                 = INetURLObject::WAS_ENCODED,
             INetURLObject::DecodeMechanism eDecodeMechanism
                 = INetURLObject::DECODE_TO_IURI,
             rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8,
             bool bRelativeNonURIs = false,
             INetURLObject::FSysStyle eStyle = INetURLObject::FSYS_DETECT);

/**
   @ATT
   Calling this function with defaulted arguments rMaybeFileHdl = Link() and
   bCheckFileExists = true often leads to results that are not intended:
   Whenever the given rTheBaseURIRef is a file URL, the given rTheRelURIRef is
   relative, and rTheRelURIRef could also be smart-parsed as a non-file URL
   (e.g., the relative URL "foo/bar" can be smart-parsed as "http://foo/bar"),
   then SmartRel2Abs called with rMaybeFileHdl = Link() and bCheckFileExists =
   true returns the non-file URL interpretation.  To avoid this, either pass
   some non-null rMaybeFileHdl if you want to check generated file URLs for
   existence (see URIHelper::GetMaybeFileHdl), or use bCheckFileExists = false
   if you want to generate file URLs without checking for their existence.
*/
UniString
SmartRel2Abs(INetURLObject const & rTheBaseURIRef,
             UniString const & rTheRelURIRef,
             Link const & rMaybeFileHdl = Link(),
             bool bCheckFileExists = true,
             bool bIgnoreFragment = false,
             INetURLObject::EncodeMechanism eEncodeMechanism
                 = INetURLObject::WAS_ENCODED,
             INetURLObject::DecodeMechanism eDecodeMechanism
                 = INetURLObject::DECODE_TO_IURI,
             rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8,
             bool bRelativeNonURIs = false,
             INetURLObject::FSysStyle eStyle = INetURLObject::FSYS_DETECT);

//============================================================================
void SetMaybeFileHdl(Link const & rTheMaybeFileHdl);

//============================================================================
Link GetMaybeFileHdl();

/**
   Converts a URI reference to a relative one, ignoring certain differences (for
   example, treating file URLs for case-ignoring file systems
   case-insensitively).

   @param context a component context; must not be null

   @param baseUriReference a base URI reference

   @param uriReference a URI reference

   @return a URI reference representing the given uriReference relative to the
   given baseUriReference; if the given baseUriReference is not an absolute,
   hierarchical URI reference, or the given uriReference is not a valid URI
   reference, null is returned

   @exception std::bad_alloc if an out-of-memory condition occurs

   @exception com::sun::star::uno::RuntimeException if any error occurs
 */
com::sun::star::uno::Reference< com::sun::star::uri::XUriReference >
normalizedMakeRelative(
    com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >
    const & context,
    rtl::OUString const & baseUriReference, rtl::OUString const & uriReference);

/**
   A variant of normalizedMakeRelative with a simplified interface.

   Internally calls normalizedMakeRelative with the default component context.

   @param baseUriReference a base URI reference, passed to
   normalizedMakeRelative

   @param uriReference a URI reference, passed to normalizedMakeRelative

   @return if the XUriReference returnd by normalizedMakeRelative is empty,
   uriReference is returned unmodified; otherwise, the result of calling
   XUriReference::getUriReference on the XUriReference returnd by
   normalizedMakeRelative is returned

   @exception std::bad_alloc if an out-of-memory condition occurs

   @exception com::sun::star::uno::RuntimeException if any error occurs

   @deprecated
   No code should rely on the default component context.
*/
rtl::OUString simpleNormalizedMakeRelative(
    rtl::OUString const & baseUriReference, rtl::OUString const & uriReference);

//============================================================================
UniString
FindFirstURLInText(UniString const & rText,
                   xub_StrLen & rBegin,
                   xub_StrLen & rEnd,
                   CharClass const & rCharClass,
                   INetURLObject::EncodeMechanism eMechanism
                       = INetURLObject::WAS_ENCODED,
                   rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8,
                   INetURLObject::FSysStyle eStyle
                       = INetURLObject::FSYS_DETECT);

//============================================================================
/** Remove any password component from both absolute and relative URLs.

    @ATT  The current implementation will not remove a password from a
    relative URL that has an authority component (e.g., the password is not
    removed from the relative ftp URL <//user:password@domain/path>).  But
    since our functions to translate between absolute and relative URLs never
    produce relative URLs with authority components, this is no real problem.

    @ATT  For relative URLs (or anything not recognized as an absolute URI),
    the current implementation will return the input unmodified, not applying
    any translations implied by the encode/decode parameters.

    @param rURI  An absolute or relative URI reference.

    @param eEncodeMechanism  See the general discussion for INetURLObject set-
    methods.

    @param eDecodeMechanism  See the general discussion for INetURLObject get-
    methods.

    @param eCharset  See the general discussion for INetURLObject get- and
    set-methods.

    @return  The input URI with any password component removed.
 */
UniString
removePassword(UniString const & rURI,
               INetURLObject::EncodeMechanism eEncodeMechanism
                   = INetURLObject::WAS_ENCODED,
               INetURLObject::DecodeMechanism eDecodeMechanism
                   = INetURLObject::DECODE_TO_IURI,
               rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8);

//============================================================================
/** Query the notational conventions used in the file system provided by some
    file content provider.

    @param rFileUrl  This file URL determines which file content provider is
    used to query the desired information.  (The UCB's usual mapping from URLs
    to content providers is used.)

    @param bAddConvenienceStyles  If true, the return value contains not only
    the style bit corresponding to the queried content provider's conventions,
    but may also contain additional style bits that make using this function
    more convenient in certain situations.  Currently, the effect is that
    FSYS_UNX is extended with FSYS_VOS, and both FSYS_DOS and FSYS_MAC are
    extended with FSYS_VOS and FSYS_UNX (i.e., the---unambiguous---detection
    of VOS style and Unix style file system paths is always enabled); also, in
    case the content provider's conventions cannot be determined, FSYS_DETECT
    is returned instead of FSysStyle(0).

    @return  The style bit corresponding to the queried content provider's
    conventions, or FSysStyle(0) if these cannot be determined.
 */
INetURLObject::FSysStyle queryFSysStyle(UniString const & rFileUrl,
                                        bool bAddConvenienceStyles = true)
    throw (com::sun::star::uno::RuntimeException);

}

#endif // SVTOOLS_URIHELPER_HXX
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stest.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 15:32:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#include <svmedit.hxx>

#ifndef _TXTCMP_HXX //autogen
#include <txtcmp.hxx>
#endif

#ifndef _SV_BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _SV_WRKWIN_HXX //autogen
#include <vcl/wrkwin.hxx>
#endif

#ifndef _SV_FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif

#ifndef _SV_SVAPP_HXX //autogen
#include <vcl/svapp.hxx>
#endif

class MyApp : public Application
{
public:
    virtual void Main( );
};

class SearchWindow : public WorkWindow
{
    PushButton      aPB;
    FixedText       aFT1, aFT2, aFT3;
    MultiLineEdit   aEText, aESrch;
    RadioButton     aModeN, aModeR, aModeL;
    SearchParam     aParam;

public:
                    SearchWindow();

    DECL_LINK( ClickHdl, Button * );
};

// --- SearchWindow::SearchWindow() ------------------------------------

SearchWindow::SearchWindow() :
                WorkWindow( NULL, WinBits( WB_APP | WB_STDWORK )),
    aPB( this, WinBits( 0 )),
    aFT1( this, WinBits( 0 )),
    aFT2( this, WinBits( 0 )),
    aFT3( this, WinBits( 0 )),
    aEText( this, WinBits( WB_BORDER )),
    aESrch( this, WinBits( WB_BORDER )),
    aModeN( this, WinBits( 0 )),
    aModeR( this, WinBits( 0 )),
    aModeL( this, WinBits( 0 )),
    aParam( "" )
{
    aPB.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));
    aModeN.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));
    aModeR.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));
    aModeL.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));

    SetMapMode( MapMode( MAP_APPFONT ));
    SetSizePixel( LogicToPixel( Size( 300, 180 ) ) );

    aEText.SetPosSizePixel( LogicToPixel( Point( 0, 22 )), LogicToPixel(Size( 270, 32 )) );
    aFT1.SetPosSizePixel( LogicToPixel( Point( 0, 10 )), LogicToPixel(Size( 18, 11 )) );
    aFT2.SetPosSizePixel( LogicToPixel( Point( 0, 60 )), LogicToPixel(Size( 24, 10 )) );
    aESrch.SetPosSizePixel( LogicToPixel( Point( 0, 70 )), LogicToPixel(Size( 270, 24 )) );
    aPB.SetPosSizePixel( LogicToPixel( Point( 223, 139 )), LogicToPixel(Size( 48, 12 )) );
    aFT3.SetPosSizePixel( LogicToPixel( Point( 0, 104 )), LogicToPixel(Size( 270, 15 )) );
    aModeN.SetPosSizePixel( LogicToPixel( Point( 5, 116 ) ), LogicToPixel( Size( 40, 12 ) ) );
    aModeR.SetPosSizePixel( LogicToPixel( Point( 5, 126 ) ), LogicToPixel( Size( 40, 12 ) ) );
    aModeL.SetPosSizePixel( LogicToPixel( Point( 5, 136 ) ), LogicToPixel( Size( 40, 12 ) ) );

    aEText.Show();
    aFT1.Show();
    aFT2.Show();
    aESrch.Show();
    aPB.Show();
    aFT3.Show();
    aModeN.Show();
    aModeR.Show();
    aModeL.Show();

    aFT3.SetText( "gefunden:" );
    aFT1.SetText( "Text:" );
    aFT2.SetText( "Suche:" );
    aPB.SetText( "starte Suche" );
    aModeN.SetText( "normal" );
    aModeR.SetText( "RegExp" );
    aModeL.SetText( "LevDis" );

    SetText( "Such-Demo" );
}

// --- SearchWindow::SearchSelectHdl() ---------------------------------

IMPL_LINK( SearchWindow, ClickHdl, Button *, pButton )
{
    if( pButton == &aPB )
    {
        String sText( aEText.GetText() );
        String sSrch( aESrch.GetText() );

/*      InfoBox( this, String( "T: " ) + sText +
                       String( "\nS: " ) + sSrch ).Execute();
*/
        BOOL bRet = FALSE;
        USHORT nStt = 0, nEnd = sText.Len();

        {
            aParam.SetSrchStr( sSrch );
            SearchText aSrchText( aParam, GetpApp()->GetAppInternational() );
            bRet = aSrchText.SearchFrwrd( sText, &nStt, &nEnd );

//          BOOL SearchBkwrd( const String &rStr, USHORT* pStart, USHORT* pEnde );
        }

        String sFound( "gefunden" );
        if( !bRet )
            sFound.Insert( "nicht ", 0 );

        sFound += ": S<";
        sFound += nStt;
        sFound += "> E<";
        sFound += nEnd;
        sFound += '>';

        if( bRet )
        {
            sFound += '<';
            sFound += sText.Copy( nStt, nEnd - nStt +1 );
            sFound += '>';
        }

        aFT3.SetText( sFound );
    }
    else if( pButton == &aModeN )
    {
        aParam.SetSrchType( SearchParam::SRCH_NORMAL );
    }
    else if( pButton == &aModeR )
    {
        aParam.SetSrchType( SearchParam::SRCH_REGEXP );
    }
    else if( pButton == &aModeL )
    {
        aParam.SetSrchType( SearchParam::SRCH_LEVDIST );
    }
    return 0;
}

// --- MyApp::Main() -----------------------------------------------

void MyApp::Main( )
{
    SearchWindow*   pSearchWindow = new SearchWindow;
    pSearchWindow->Show();
    Execute();
    delete pSearchWindow;

}

// --- aMyApp ------------------------------------------------------

MyApp aMyApp;
<commit_msg>INTEGRATION: CWS vgbugs07 (1.4.200); FILE MERGED 2007/06/04 13:31:48 vg 1.4.200.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: stest.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 22:04:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svtools.hxx"
#include <svtools/svmedit.hxx>

#ifndef _TXTCMP_HXX //autogen
#include <txtcmp.hxx>
#endif

#ifndef _SV_BUTTON_HXX //autogen
#include <vcl/button.hxx>
#endif

#ifndef _SV_WRKWIN_HXX //autogen
#include <vcl/wrkwin.hxx>
#endif

#ifndef _SV_FIXED_HXX //autogen
#include <vcl/fixed.hxx>
#endif

#ifndef _SV_SVAPP_HXX //autogen
#include <vcl/svapp.hxx>
#endif

class MyApp : public Application
{
public:
    virtual void Main( );
};

class SearchWindow : public WorkWindow
{
    PushButton      aPB;
    FixedText       aFT1, aFT2, aFT3;
    MultiLineEdit   aEText, aESrch;
    RadioButton     aModeN, aModeR, aModeL;
    SearchParam     aParam;

public:
                    SearchWindow();

    DECL_LINK( ClickHdl, Button * );
};

// --- SearchWindow::SearchWindow() ------------------------------------

SearchWindow::SearchWindow() :
                WorkWindow( NULL, WinBits( WB_APP | WB_STDWORK )),
    aPB( this, WinBits( 0 )),
    aFT1( this, WinBits( 0 )),
    aFT2( this, WinBits( 0 )),
    aFT3( this, WinBits( 0 )),
    aEText( this, WinBits( WB_BORDER )),
    aESrch( this, WinBits( WB_BORDER )),
    aModeN( this, WinBits( 0 )),
    aModeR( this, WinBits( 0 )),
    aModeL( this, WinBits( 0 )),
    aParam( "" )
{
    aPB.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));
    aModeN.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));
    aModeR.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));
    aModeL.SetClickHdl( LINK( this, SearchWindow, ClickHdl ));

    SetMapMode( MapMode( MAP_APPFONT ));
    SetSizePixel( LogicToPixel( Size( 300, 180 ) ) );

    aEText.SetPosSizePixel( LogicToPixel( Point( 0, 22 )), LogicToPixel(Size( 270, 32 )) );
    aFT1.SetPosSizePixel( LogicToPixel( Point( 0, 10 )), LogicToPixel(Size( 18, 11 )) );
    aFT2.SetPosSizePixel( LogicToPixel( Point( 0, 60 )), LogicToPixel(Size( 24, 10 )) );
    aESrch.SetPosSizePixel( LogicToPixel( Point( 0, 70 )), LogicToPixel(Size( 270, 24 )) );
    aPB.SetPosSizePixel( LogicToPixel( Point( 223, 139 )), LogicToPixel(Size( 48, 12 )) );
    aFT3.SetPosSizePixel( LogicToPixel( Point( 0, 104 )), LogicToPixel(Size( 270, 15 )) );
    aModeN.SetPosSizePixel( LogicToPixel( Point( 5, 116 ) ), LogicToPixel( Size( 40, 12 ) ) );
    aModeR.SetPosSizePixel( LogicToPixel( Point( 5, 126 ) ), LogicToPixel( Size( 40, 12 ) ) );
    aModeL.SetPosSizePixel( LogicToPixel( Point( 5, 136 ) ), LogicToPixel( Size( 40, 12 ) ) );

    aEText.Show();
    aFT1.Show();
    aFT2.Show();
    aESrch.Show();
    aPB.Show();
    aFT3.Show();
    aModeN.Show();
    aModeR.Show();
    aModeL.Show();

    aFT3.SetText( "gefunden:" );
    aFT1.SetText( "Text:" );
    aFT2.SetText( "Suche:" );
    aPB.SetText( "starte Suche" );
    aModeN.SetText( "normal" );
    aModeR.SetText( "RegExp" );
    aModeL.SetText( "LevDis" );

    SetText( "Such-Demo" );
}

// --- SearchWindow::SearchSelectHdl() ---------------------------------

IMPL_LINK( SearchWindow, ClickHdl, Button *, pButton )
{
    if( pButton == &aPB )
    {
        String sText( aEText.GetText() );
        String sSrch( aESrch.GetText() );

/*      InfoBox( this, String( "T: " ) + sText +
                       String( "\nS: " ) + sSrch ).Execute();
*/
        BOOL bRet = FALSE;
        USHORT nStt = 0, nEnd = sText.Len();

        {
            aParam.SetSrchStr( sSrch );
            SearchText aSrchText( aParam, GetpApp()->GetAppInternational() );
            bRet = aSrchText.SearchFrwrd( sText, &nStt, &nEnd );

//          BOOL SearchBkwrd( const String &rStr, USHORT* pStart, USHORT* pEnde );
        }

        String sFound( "gefunden" );
        if( !bRet )
            sFound.Insert( "nicht ", 0 );

        sFound += ": S<";
        sFound += nStt;
        sFound += "> E<";
        sFound += nEnd;
        sFound += '>';

        if( bRet )
        {
            sFound += '<';
            sFound += sText.Copy( nStt, nEnd - nStt +1 );
            sFound += '>';
        }

        aFT3.SetText( sFound );
    }
    else if( pButton == &aModeN )
    {
        aParam.SetSrchType( SearchParam::SRCH_NORMAL );
    }
    else if( pButton == &aModeR )
    {
        aParam.SetSrchType( SearchParam::SRCH_REGEXP );
    }
    else if( pButton == &aModeL )
    {
        aParam.SetSrchType( SearchParam::SRCH_LEVDIST );
    }
    return 0;
}

// --- MyApp::Main() -----------------------------------------------

void MyApp::Main( )
{
    SearchWindow*   pSearchWindow = new SearchWindow;
    pSearchWindow->Show();
    Execute();
    delete pSearchWindow;

}

// --- aMyApp ------------------------------------------------------

MyApp aMyApp;
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlotParallelCoordinates.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkPlotParallelCoordinates.h"

#include "vtkChartParallelCoordinates.h"
#include "vtkContext2D.h"
#include "vtkAxis.h"
#include "vtkPen.h"
#include "vtkFloatArray.h"
#include "vtkDoubleArray.h"
#include "vtkVector.h"
#include "vtkTransform2D.h"
#include "vtkContextDevice2D.h"
#include "vtkContextMapper2D.h"
#include "vtkPoints2D.h"
#include "vtkTable.h"
#include "vtkDataArray.h"
#include "vtkIdTypeArray.h"
#include "vtkStringArray.h"
#include "vtkTimeStamp.h"
#include "vtkInformation.h"
#include "vtkSmartPointer.h"

// Need to turn some arrays of strings into categories
#include "vtkStringToCategory.h"

#include "vtkObjectFactory.h"

#include "vtkstd/vector"
#include "vtkstd/algorithm"

class vtkPlotParallelCoordinates::Private :
    public vtkstd::vector< vtkstd::vector<float> >
{
public:
  Private()
  {
    this->SelectionInitialized = false;
  }

  vtkstd::vector<float> AxisPos;
  bool SelectionInitialized;
};

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPlotParallelCoordinates);

//-----------------------------------------------------------------------------
vtkPlotParallelCoordinates::vtkPlotParallelCoordinates()
{
  this->Points = NULL;
  this->Storage = new vtkPlotParallelCoordinates::Private;
  this->Pen->SetColor(0, 0, 0, 25);
}

//-----------------------------------------------------------------------------
vtkPlotParallelCoordinates::~vtkPlotParallelCoordinates()
{
  if (this->Points)
    {
    this->Points->Delete();
    this->Points = NULL;
    }
  delete this->Storage;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::Update()
{
  if (!this->Visible)
    {
    return;
    }
  // Check if we have an input
  vtkTable *table = this->Data->GetInput();
  if (!table)
    {
    vtkDebugMacro(<< "Update event called with no input table set.");
    return;
    }

  this->UpdateTableCache(table);
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::Paint(vtkContext2D *painter)
{
  // This is where everything should be drawn, or dispatched to other methods.
  vtkDebugMacro(<< "Paint event called in vtkPlotParallelCoordinates.");

  if (!this->Visible)
    {
    return false;
    }

  // Now to plot the points
  if (this->Points)
    {
    painter->ApplyPen(this->Pen);
    painter->DrawPoly(this->Points);
    painter->GetPen()->SetLineType(vtkPen::SOLID_LINE);
    }

  painter->ApplyPen(this->Pen);

  if (this->Storage->size() == 0)
    {
    return false;
    }

  size_t cols = this->Storage->size();
  size_t rows = this->Storage->at(0).size();
  vtkVector2f* line = new vtkVector2f[cols];

  // Update the axis positions
  vtkChartParallelCoordinates *parent =
      vtkChartParallelCoordinates::SafeDownCast(this->Parent);

  for (size_t i = 0; i < cols; ++i)
    {
    this->Storage->AxisPos[i] = parent->GetAxis(int(i)) ?
                                parent->GetAxis(int(i))->GetPoint1()[0] :
                                0;
    }

  vtkIdType selection = 0;
  vtkIdType id = 0;
  vtkIdType selectionSize = 0;
  if (this->Selection)
    {
    selectionSize = this->Selection->GetNumberOfTuples();
    if (selectionSize)
      {
      this->Selection->GetTupleValue(selection, &id);
      }
    }

  // Draw all of the lines
  painter->ApplyPen(this->Pen);
  for (size_t i = 0; i < rows; ++i)
    {
    for (size_t j = 0; j < cols; ++j)
      {
      line[j].Set(this->Storage->AxisPos[j], (*this->Storage)[j][i]);
      }
    painter->DrawPoly(line[0].GetData(), static_cast<int>(cols));
    }

  // Now draw the selected lines
  if (this->Selection)
    {
    painter->GetPen()->SetColor(255, 0, 0, 100);
    for (vtkIdType i = 0; i < this->Selection->GetNumberOfTuples(); ++i)
      {
      for (size_t j = 0; j < cols; ++j)
        {
        this->Selection->GetTupleValue(i, &id);
        line[j].Set(this->Storage->AxisPos[j], (*this->Storage)[j][id]);
        }
      painter->DrawPoly(line[0].GetData(), static_cast<int>(cols));
      }
    }

  delete[] line;

  return true;
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::PaintLegend(vtkContext2D *painter, float rect[4], int )
{
  painter->ApplyPen(this->Pen);
  painter->DrawLine(rect[0], rect[1]+0.5*rect[3],
                    rect[0]+rect[2], rect[1]+0.5*rect[3]);
  return true;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::GetBounds(double *)
{

}

//-----------------------------------------------------------------------------
int vtkPlotParallelCoordinates::GetNearestPoint(const vtkVector2f& ,
                                  const vtkVector2f& ,
                                  vtkVector2f* )
{
  return -1;
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::SetSelectionRange(int axis, float low,
                                                   float high)
{
  if (!this->Selection)
    {
    return false;
    }
  if (this->Storage->SelectionInitialized)
    {
    // Further refine the selection that has already been made
    vtkIdTypeArray *array = vtkIdTypeArray::New();
    vtkstd::vector<float>& col = this->Storage->at(axis);
    for (vtkIdType i = 0; i < this->Selection->GetNumberOfTuples(); ++i)
      {
      vtkIdType id = 0;
      this->Selection->GetTupleValue(i, &id);
      if (col[id] >= low && col[id] <= high)
        {
        // Remove this point - no longer selected
        array->InsertNextValue(id);
        }
      }
    this->Selection->DeepCopy(array);
    array->Delete();
    }
  else
    {
    // First run - ensure the selection list is empty and build it up
    vtkstd::vector<float>& col = this->Storage->at(axis);
    for (size_t i = 0; i < col.size(); ++i)
      {
      if (col[i] >= low && col[i] <= high)
        {
        // Remove this point - no longer selected
        this->Selection->InsertNextValue(i);
        }
      }
    this->Storage->SelectionInitialized = true;
    }
  return true;
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::ResetSelectionRange()
{
  this->Storage->SelectionInitialized = false;
  if (this->Selection)
    {
    this->Selection->SetNumberOfTuples(0);
    }
  return true;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::SetInput(vtkTable* table)
{
  if (table == this->Data->GetInput() && (!table ||
                                          table->GetMTime() < this->BuildTime))
    {
    return;
    }

  this->vtkPlot::SetInput(table);
  vtkChartParallelCoordinates *parent =
      vtkChartParallelCoordinates::SafeDownCast(this->Parent);
  if (parent && table)
    {
    // By default make the first 10 columns visible in a plot.
    for (vtkIdType i = 0; i < table->GetNumberOfColumns() && i < 10; ++i)
      {
      parent->SetColumnVisibility(table->GetColumnName(i), true);
      }
    }
  else if (parent)
    {
    // No table, therefore no visible columns
    parent->GetVisibleColumns()->SetNumberOfTuples(0);
    }
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::UpdateTableCache(vtkTable *table)
{
  // Each axis is a column in our storage array, they are scaled from 0.0 to 1.0
  vtkChartParallelCoordinates *parent =
      vtkChartParallelCoordinates::SafeDownCast(this->Parent);
  if (!parent || !table || table->GetNumberOfColumns() == 0)
    {
    return false;
    }

  vtkStringArray* cols = parent->GetVisibleColumns();
  this->Storage->resize(cols->GetNumberOfTuples());
  this->Storage->AxisPos.resize(cols->GetNumberOfTuples());
  vtkIdType rows = table->GetNumberOfRows();

  for (vtkIdType i = 0; i < cols->GetNumberOfTuples(); ++i)
    {
    vtkstd::vector<float>& col = this->Storage->at(i);
    vtkAxis* axis = parent->GetAxis(i);
    col.resize(rows);
    vtkSmartPointer<vtkDataArray> data =
        vtkDataArray::SafeDownCast(table->GetColumnByName(cols->GetValue(i)));
    if (!data)
      {
      if (table->GetColumnByName(cols->GetValue(i))->IsA("vtkStringArray"))
        {
        // We have a different kind of column - attempt to make it into an enum
        vtkStringToCategory* stoc = vtkStringToCategory::New();
        stoc->SetInput(table);
        stoc->SetInputArrayToProcess(0, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     cols->GetValue(i));
        stoc->SetCategoryArrayName("enumPC");
        stoc->Update();
        vtkTable* table2 = vtkTable::SafeDownCast(stoc->GetOutput());
        vtkTable* stringTable = vtkTable::SafeDownCast(stoc->GetOutput(1));
        if (table2)
          {
          data = vtkDataArray::SafeDownCast(table2->GetColumnByName("enumPC"));
          }
        if (stringTable && stringTable->GetColumnByName("Strings"))
          {
          vtkStringArray* strings =
              vtkStringArray::SafeDownCast(stringTable->GetColumnByName("Strings"));
          vtkSmartPointer<vtkDoubleArray> arr =
              vtkSmartPointer<vtkDoubleArray>::New();
          for (vtkIdType j = 0; j < strings->GetNumberOfTuples(); ++j)
            {
            arr->InsertNextValue(j);
            }
          // Now we need to set the range on the string axis
          axis->SetTickLabels(strings);
          axis->SetTickPositions(arr);
          if (strings->GetNumberOfTuples() > 1)
            {
            axis->SetRange(0.0, strings->GetNumberOfTuples()-1);
            }
          else
            {
            axis->SetRange(-0.1, 0.1);
            }
          axis->Update();
          }
        stoc->Delete();
        }
      // If we still don't have a valid data array then skip this column.
      if (!data)
        {
        continue;
        }
      }

    // Also need the range from the appropriate axis, to normalize points
    float min = axis->GetMinimum();
    float max = axis->GetMaximum();
    float scale = 1.0f / (max - min);

    for (vtkIdType j = 0; j < rows; ++j)
      {
      col[j] = (data->GetTuple1(j)-min) * scale;
      }
    }

  this->BuildTime.Modified();
  return true;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<commit_msg>COMP: Include STL headers directly.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkPlotParallelCoordinates.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include "vtkPlotParallelCoordinates.h"

#include "vtkChartParallelCoordinates.h"
#include "vtkContext2D.h"
#include "vtkAxis.h"
#include "vtkPen.h"
#include "vtkFloatArray.h"
#include "vtkDoubleArray.h"
#include "vtkVector.h"
#include "vtkTransform2D.h"
#include "vtkContextDevice2D.h"
#include "vtkContextMapper2D.h"
#include "vtkPoints2D.h"
#include "vtkTable.h"
#include "vtkDataArray.h"
#include "vtkIdTypeArray.h"
#include "vtkStringArray.h"
#include "vtkTimeStamp.h"
#include "vtkInformation.h"
#include "vtkSmartPointer.h"

// Need to turn some arrays of strings into categories
#include "vtkStringToCategory.h"

#include "vtkObjectFactory.h"

#include <vector>
#include <algorithm>

class vtkPlotParallelCoordinates::Private :
    public std::vector< std::vector<float> >
{
public:
  Private()
  {
    this->SelectionInitialized = false;
  }

  std::vector<float> AxisPos;
  bool SelectionInitialized;
};

//-----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPlotParallelCoordinates);

//-----------------------------------------------------------------------------
vtkPlotParallelCoordinates::vtkPlotParallelCoordinates()
{
  this->Points = NULL;
  this->Storage = new vtkPlotParallelCoordinates::Private;
  this->Pen->SetColor(0, 0, 0, 25);
}

//-----------------------------------------------------------------------------
vtkPlotParallelCoordinates::~vtkPlotParallelCoordinates()
{
  if (this->Points)
    {
    this->Points->Delete();
    this->Points = NULL;
    }
  delete this->Storage;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::Update()
{
  if (!this->Visible)
    {
    return;
    }
  // Check if we have an input
  vtkTable *table = this->Data->GetInput();
  if (!table)
    {
    vtkDebugMacro(<< "Update event called with no input table set.");
    return;
    }

  this->UpdateTableCache(table);
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::Paint(vtkContext2D *painter)
{
  // This is where everything should be drawn, or dispatched to other methods.
  vtkDebugMacro(<< "Paint event called in vtkPlotParallelCoordinates.");

  if (!this->Visible)
    {
    return false;
    }

  // Now to plot the points
  if (this->Points)
    {
    painter->ApplyPen(this->Pen);
    painter->DrawPoly(this->Points);
    painter->GetPen()->SetLineType(vtkPen::SOLID_LINE);
    }

  painter->ApplyPen(this->Pen);

  if (this->Storage->size() == 0)
    {
    return false;
    }

  size_t cols = this->Storage->size();
  size_t rows = this->Storage->at(0).size();
  vtkVector2f* line = new vtkVector2f[cols];

  // Update the axis positions
  vtkChartParallelCoordinates *parent =
      vtkChartParallelCoordinates::SafeDownCast(this->Parent);

  for (size_t i = 0; i < cols; ++i)
    {
    this->Storage->AxisPos[i] = parent->GetAxis(int(i)) ?
                                parent->GetAxis(int(i))->GetPoint1()[0] :
                                0;
    }

  vtkIdType selection = 0;
  vtkIdType id = 0;
  vtkIdType selectionSize = 0;
  if (this->Selection)
    {
    selectionSize = this->Selection->GetNumberOfTuples();
    if (selectionSize)
      {
      this->Selection->GetTupleValue(selection, &id);
      }
    }

  // Draw all of the lines
  painter->ApplyPen(this->Pen);
  for (size_t i = 0; i < rows; ++i)
    {
    for (size_t j = 0; j < cols; ++j)
      {
      line[j].Set(this->Storage->AxisPos[j], (*this->Storage)[j][i]);
      }
    painter->DrawPoly(line[0].GetData(), static_cast<int>(cols));
    }

  // Now draw the selected lines
  if (this->Selection)
    {
    painter->GetPen()->SetColor(255, 0, 0, 100);
    for (vtkIdType i = 0; i < this->Selection->GetNumberOfTuples(); ++i)
      {
      for (size_t j = 0; j < cols; ++j)
        {
        this->Selection->GetTupleValue(i, &id);
        line[j].Set(this->Storage->AxisPos[j], (*this->Storage)[j][id]);
        }
      painter->DrawPoly(line[0].GetData(), static_cast<int>(cols));
      }
    }

  delete[] line;

  return true;
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::PaintLegend(vtkContext2D *painter, float rect[4], int )
{
  painter->ApplyPen(this->Pen);
  painter->DrawLine(rect[0], rect[1]+0.5*rect[3],
                    rect[0]+rect[2], rect[1]+0.5*rect[3]);
  return true;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::GetBounds(double *)
{

}

//-----------------------------------------------------------------------------
int vtkPlotParallelCoordinates::GetNearestPoint(const vtkVector2f& ,
                                  const vtkVector2f& ,
                                  vtkVector2f* )
{
  return -1;
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::SetSelectionRange(int axis, float low,
                                                   float high)
{
  if (!this->Selection)
    {
    return false;
    }
  if (this->Storage->SelectionInitialized)
    {
    // Further refine the selection that has already been made
    vtkIdTypeArray *array = vtkIdTypeArray::New();
    std::vector<float>& col = this->Storage->at(axis);
    for (vtkIdType i = 0; i < this->Selection->GetNumberOfTuples(); ++i)
      {
      vtkIdType id = 0;
      this->Selection->GetTupleValue(i, &id);
      if (col[id] >= low && col[id] <= high)
        {
        // Remove this point - no longer selected
        array->InsertNextValue(id);
        }
      }
    this->Selection->DeepCopy(array);
    array->Delete();
    }
  else
    {
    // First run - ensure the selection list is empty and build it up
    std::vector<float>& col = this->Storage->at(axis);
    for (size_t i = 0; i < col.size(); ++i)
      {
      if (col[i] >= low && col[i] <= high)
        {
        // Remove this point - no longer selected
        this->Selection->InsertNextValue(i);
        }
      }
    this->Storage->SelectionInitialized = true;
    }
  return true;
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::ResetSelectionRange()
{
  this->Storage->SelectionInitialized = false;
  if (this->Selection)
    {
    this->Selection->SetNumberOfTuples(0);
    }
  return true;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::SetInput(vtkTable* table)
{
  if (table == this->Data->GetInput() && (!table ||
                                          table->GetMTime() < this->BuildTime))
    {
    return;
    }

  this->vtkPlot::SetInput(table);
  vtkChartParallelCoordinates *parent =
      vtkChartParallelCoordinates::SafeDownCast(this->Parent);
  if (parent && table)
    {
    // By default make the first 10 columns visible in a plot.
    for (vtkIdType i = 0; i < table->GetNumberOfColumns() && i < 10; ++i)
      {
      parent->SetColumnVisibility(table->GetColumnName(i), true);
      }
    }
  else if (parent)
    {
    // No table, therefore no visible columns
    parent->GetVisibleColumns()->SetNumberOfTuples(0);
    }
}

//-----------------------------------------------------------------------------
bool vtkPlotParallelCoordinates::UpdateTableCache(vtkTable *table)
{
  // Each axis is a column in our storage array, they are scaled from 0.0 to 1.0
  vtkChartParallelCoordinates *parent =
      vtkChartParallelCoordinates::SafeDownCast(this->Parent);
  if (!parent || !table || table->GetNumberOfColumns() == 0)
    {
    return false;
    }

  vtkStringArray* cols = parent->GetVisibleColumns();
  this->Storage->resize(cols->GetNumberOfTuples());
  this->Storage->AxisPos.resize(cols->GetNumberOfTuples());
  vtkIdType rows = table->GetNumberOfRows();

  for (vtkIdType i = 0; i < cols->GetNumberOfTuples(); ++i)
    {
    std::vector<float>& col = this->Storage->at(i);
    vtkAxis* axis = parent->GetAxis(i);
    col.resize(rows);
    vtkSmartPointer<vtkDataArray> data =
        vtkDataArray::SafeDownCast(table->GetColumnByName(cols->GetValue(i)));
    if (!data)
      {
      if (table->GetColumnByName(cols->GetValue(i))->IsA("vtkStringArray"))
        {
        // We have a different kind of column - attempt to make it into an enum
        vtkStringToCategory* stoc = vtkStringToCategory::New();
        stoc->SetInput(table);
        stoc->SetInputArrayToProcess(0, 0, 0,
                                     vtkDataObject::FIELD_ASSOCIATION_ROWS,
                                     cols->GetValue(i));
        stoc->SetCategoryArrayName("enumPC");
        stoc->Update();
        vtkTable* table2 = vtkTable::SafeDownCast(stoc->GetOutput());
        vtkTable* stringTable = vtkTable::SafeDownCast(stoc->GetOutput(1));
        if (table2)
          {
          data = vtkDataArray::SafeDownCast(table2->GetColumnByName("enumPC"));
          }
        if (stringTable && stringTable->GetColumnByName("Strings"))
          {
          vtkStringArray* strings =
              vtkStringArray::SafeDownCast(stringTable->GetColumnByName("Strings"));
          vtkSmartPointer<vtkDoubleArray> arr =
              vtkSmartPointer<vtkDoubleArray>::New();
          for (vtkIdType j = 0; j < strings->GetNumberOfTuples(); ++j)
            {
            arr->InsertNextValue(j);
            }
          // Now we need to set the range on the string axis
          axis->SetTickLabels(strings);
          axis->SetTickPositions(arr);
          if (strings->GetNumberOfTuples() > 1)
            {
            axis->SetRange(0.0, strings->GetNumberOfTuples()-1);
            }
          else
            {
            axis->SetRange(-0.1, 0.1);
            }
          axis->Update();
          }
        stoc->Delete();
        }
      // If we still don't have a valid data array then skip this column.
      if (!data)
        {
        continue;
        }
      }

    // Also need the range from the appropriate axis, to normalize points
    float min = axis->GetMinimum();
    float max = axis->GetMaximum();
    float scale = 1.0f / (max - min);

    for (vtkIdType j = 0; j < rows; ++j)
      {
      col[j] = (data->GetTuple1(j)-min) * scale;
      }
    }

  this->BuildTime.Modified();
  return true;
}

//-----------------------------------------------------------------------------
void vtkPlotParallelCoordinates::PrintSelf(ostream &os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}
<|endoftext|>