<commit_before>/***************************************************************************
 *  common/verbose.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <stxxl/bits/verbose.h>
#include <stxxl/bits/common/log.h>
#include <stxxl/bits/common/timer.h>

#ifdef STXXL_BOOST_CONFIG
#include <boost/config.hpp>
#endif

#ifdef BOOST_MSVC
#define snprintf _snprintf
#endif

__STXXL_BEGIN_NAMESPACE

static const double program_start_time_stamp = timestamp();

void print_msg(const char * label, const std::string & msg, unsigned flags)
{
    std::string s;
    if (flags & _STXXL_PRNT_TIMESTAMP) {
        double t = timestamp() - program_start_time_stamp;
        char tstr[23]; /* "[364:23:59:59.999999] " */
        snprintf(tstr, sizeof(tstr), "[%d.%02d:%02d:%02d.%06d] ",
                int(t / (24 * 60 * 60)),
                int(t / (60 * 60)) % 24,
                int(t / 60) % 60, int(t) % 60,
                int((t - floor(t)) * 10000));
        s += tstr;
    }
    if (label) {
        s += '[';
        s += label;
        s += "] ";
    }
    s += msg;
    if (flags & _STXXL_PRNT_ADDNEWLINE)
        s += '\n';
    if (flags & _STXXL_PRNT_COUT)
        std::cout << s << std::flush;
    if (flags & _STXXL_PRNT_CERR)
        std::cerr << s << std::flush;
    logger * logger_instance = logger::get_instance();
    if (flags & _STXXL_PRNT_LOG)
        logger_instance->log_stream() << s << std::flush;
    if (flags & _STXXL_PRNT_ERRLOG)
        logger_instance->errlog_stream() << s << std::flush;
}

__STXXL_END_NAMESPACE

// vim: et:ts=4:sw=4
<commit_msg>correctly scale fractional seconds<commit_after>/***************************************************************************
 *  common/verbose.cpp
 *
 *  Part of the STXXL. See http://stxxl.sourceforge.net
 *
 *  Copyright (C) 2009 Andreas Beckmann <beckmann@cs.uni-frankfurt.de>
 *
 *  Distributed under the Boost Software License, Version 1.0.
 *  (See accompanying file LICENSE_1_0.txt or copy at
 *  http://www.boost.org/LICENSE_1_0.txt)
 **************************************************************************/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <stxxl/bits/verbose.h>
#include <stxxl/bits/common/log.h>
#include <stxxl/bits/common/timer.h>

#ifdef STXXL_BOOST_CONFIG
#include <boost/config.hpp>
#endif

#ifdef BOOST_MSVC
#define snprintf _snprintf
#endif

__STXXL_BEGIN_NAMESPACE

static const double program_start_time_stamp = timestamp();

void print_msg(const char * label, const std::string & msg, unsigned flags)
{
    std::string s;
    if (flags & _STXXL_PRNT_TIMESTAMP) {
        double t = timestamp() - program_start_time_stamp;
        char tstr[23]; /* "[364:23:59:59.999999] " */
        snprintf(tstr, sizeof(tstr), "[%d.%02d:%02d:%02d.%06d] ",
                int(t / (24 * 60 * 60)),
                int(t / (60 * 60)) % 24,
                int(t / 60) % 60, int(t) % 60,
                int((t - floor(t)) * 1000000));
        s += tstr;
    }
    if (label) {
        s += '[';
        s += label;
        s += "] ";
    }
    s += msg;
    if (flags & _STXXL_PRNT_ADDNEWLINE)
        s += '\n';
    if (flags & _STXXL_PRNT_COUT)
        std::cout << s << std::flush;
    if (flags & _STXXL_PRNT_CERR)
        std::cerr << s << std::flush;
    logger * logger_instance = logger::get_instance();
    if (flags & _STXXL_PRNT_LOG)
        logger_instance->log_stream() << s << std::flush;
    if (flags & _STXXL_PRNT_ERRLOG)
        logger_instance->errlog_stream() << s << std::flush;
}

__STXXL_END_NAMESPACE

// vim: et:ts=4:sw=4
<|endoftext|>


<commit_before>#include "k/context.h"

#include "etl/array_count.h"
#include "etl/armv7m/mpu.h"
#include "etl/armv7m/types.h"

#include "common/abi_sizes.h"
#include "common/message.h"
#include "common/descriptor.h"

#include "k/memory.h"
#include "k/context_layout.h"
#include "k/object_table.h"
#include "k/registers.h"
#include "k/reply_gate.h"
#include "k/reply_sender.h"
#include "k/scheduler.h"
#include "k/unprivileged.h"

using etl::armv7m::Word;

namespace k {

template struct ObjectSubclassChecks<Context, kabi::context_size>;

static_assert(__builtin_offsetof(Context::Body, save) == 0,
    "Context::Body::save offset is wrong (should be zero, isn't)");

static_assert(K_CONTEXT_BODY_STACK_OFFSET ==
    __builtin_offsetof(Context::Body, save.named.stack),
    "K_CONTEXT_BODY_STACK_OFFSET is wrong");

/*******************************************************************************
 * Context-specific stuff
 */

Context::Context(Generation g, Body & body)
  : Object{g},
    _body(body) {
  body.ctx_item.owner = this;
  body.sender_item.owner = this;
}

void Context::nullify_exchanged_keys(unsigned preserved) {
  // Had to do this somewhere, this is as good a place as any.
  // (The fields in question are private, so this can't be at top level.)
  // (Putting it in the ctor hits the ill-defined non-trivial ctor rules.)
  static_assert(K_CONTEXT_BODY_OFFSET == __builtin_offsetof(Context, _body),
                "K_CONTEXT_BODY_OFFSET is wrong");

  // Right, actual implementation now:
  for (unsigned i = preserved; i < config::n_message_keys; ++i) {
    _body.keys[i] = Key::null();
  }
}

void Context::set_reply_gate(ReplyGate & g) {
  ETL_ASSERT(!g.is_bound());
  _body.reply_gate = &g;
  g.set_owner(this);
}

uint32_t Context::do_ipc(uint32_t stack, Descriptor d) {
  set_stack(stack);

  // Perform first phase of IPC.
  if (d.get_send_enabled()) {
    key(d.get_target()).deliver_from(this);
  } else if (d.get_receive_enabled()) {
    key(d.get_source()).get()->deliver_to(this);
  }
  // Note that if neither bit is set, we'll just return with the registers
  // unchanged.

  do_deferred_switch();

  return current->stack();
}

void Context::do_key_op(uint32_t sysnum, Descriptor d) {
  switch (sysnum) {
    case 1:  // Copy Key
      key(d.get_target()) = key(d.get_source());
      return;

    case 2:  // Discard Keys
      for (unsigned k = d.get_source(); k <= d.get_target(); ++k) {
        key(k) = Key::null();
      }
      return;

    default:
      // Bad sysnum used.  This should probably become a fault?
      return;
  }
}

void Context::complete_receive(BlockingSender * sender) {
  _body.save.sys = sender->on_blocked_delivery_accepted(get_message_keys());
}

void Context::complete_receive(Exception e, uint32_t param) {
  _body.save.sys = { Message::failure(e, param), 0 };
  nullify_exchanged_keys();
}

void Context::block_in_receive(List<Context> & list) {
  // TODO should we decide to permit non-blocking recieves... here's the spot.
  _body.ctx_item.unlink();
  list.insert(&_body.ctx_item);
  _body.state = State::receiving;

  pend_switch();
}

void Context::block_in_reply() {
  _body.ctx_item.unlink();
  _body.state = State::receiving;

  pend_switch();
}

void Context::complete_blocked_receive(Brand brand, Sender * sender) {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;
  _body.save.sys.brand = brand;

  pend_switch();

  _body.save.sys.m = sender->on_delivery_accepted(get_message_keys());
}

void Context::complete_blocked_receive(Exception e, uint32_t param) {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;

  pend_switch();

  complete_receive(e, param);
}

void Context::apply_to_mpu() {
  using etl::armv7m::mpu;

  for (unsigned i = 0; i < config::n_task_regions; ++i) {
    mpu.write_rnr(i);
    auto object = _body.memory_regions[i].get();
    auto region =
        object->get_region_for_brand(_body.memory_regions[i].get_brand());
    mpu.write_rbar(region.rbar);
    mpu.write_rasr(region.rasr);
  }
}

void Context::make_runnable() {
  switch (_body.state) {
    case State::sending:
      _body.sender_item.unlink();
      on_blocked_delivery_aborted();
      break;

    case State::receiving:
      _body.ctx_item.unlink();
      complete_blocked_receive(Exception::would_block);
      break;

    case State::stopped:
      runnable.insert(&_body.ctx_item);
      _body.state = State::runnable;
      break;

    case State::runnable:
      break;
  }
}

/*******************************************************************************
 * Implementation of Sender and BlockingSender
 */

Priority Context::get_priority() const {
  return _body.priority;
}

Message Context::on_delivery_accepted(Keys & k) {
  auto d = get_descriptor();

  auto m = _body.save.sys.m.sanitized();

  k.keys[0] = d.is_call() ? make_reply_key() : Key::null();
  for (unsigned ki = 1; ki < config::n_message_keys; ++ki) {
    k.keys[ki] = key(ki);
  }

  if (d.get_receive_enabled()) {
    auto & source = d.is_call() ? k.keys[0]
                                : key(d.get_source());
    source.get()->deliver_to(this);
  }

  return m;
}

void Context::block_in_send(Brand brand, List<BlockingSender> & list) {
  ETL_ASSERT(this == current);

  if (get_descriptor().get_block()) {
    _body.saved_brand = brand;
    list.insert(&_body.sender_item);
    _body.ctx_item.unlink();
    _body.state = State::sending;

    pend_switch();
  } else {
    // Unprivileged code is unwilling to block for delivery.
    _body.save.sys = { Message::failure(Exception::would_block), 0 };
  }
}

ReceivedMessage Context::on_blocked_delivery_accepted(Keys & k) {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;

  pend_switch();
  return {
    .m = on_delivery_accepted(k),
    .brand = _body.saved_brand,
  };
}

void Context::on_blocked_delivery_aborted() {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;
  pend_switch();

  _body.save.sys = { Message::failure(Exception::would_block), 0 };
}

Key Context::make_reply_key() const {
  if (_body.reply_gate) {
    auto maybe_key = _body.reply_gate.ref()->make_key(0);
    if (maybe_key) return maybe_key.ref();
  }
  return Key::null();
}

/*******************************************************************************
 * Implementation of Context protocol.
 */

using IpcImpl = void (Context::*)(ScopedReplySender &,
                                  Brand,
                                  Message const &,
                                  Keys &);

void Context::deliver_from(Brand brand, Sender * sender) {
  Keys k;
  Message m = sender->on_delivery_accepted(k);

  static constexpr IpcImpl dispatch[] {
    &Context::do_read_register,
    &Context::do_write_register,
    &Context::do_read_key,
    &Context::do_write_key,
    &Context::do_read_region,
    &Context::do_write_region,
    &Context::do_make_runnable,
    &Context::do_read_priority,
    &Context::do_write_priority,
    &Context::do_save_kernel_registers,
    &Context::do_restore_kernel_registers,
  };
  if (m.d0.get_selector() < etl::array_count(dispatch)) {
    ScopedReplySender reply_sender{k.keys[0]};
    auto fn = dispatch[m.d0.get_selector()];
    (this->*fn)(reply_sender, brand, m, k);
  } else {
    do_badop(m, k);
  }
}

void Context::do_read_register(ScopedReplySender & reply_sender,
                               Brand,
                               Message const & arg,
                               Keys &) {
  if (arg.d1 < etl::array_count(_body.save.raw)) {
    reply_sender.get_message().d1 = _body.save.raw[arg.d1];
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_write_register(ScopedReplySender & reply_sender,
                                Brand,
                                Message const & arg,
                                Keys &) {
  if (arg.d1 < etl::array_count(_body.save.raw)) {
    _body.save.raw[arg.d1] = arg.d2;
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_read_key(ScopedReplySender & reply_sender,
                          Brand,
                          Message const & arg,
                          Keys &) {
  auto r = arg.d1;

  if (r >= config::n_task_keys) {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  } else {
    reply_sender.set_key(1, key(r));
  }
}

void Context::do_write_key(ScopedReplySender & reply_sender,
                           Brand,
                           Message const & arg,
                           Keys & k) {
  auto r = arg.d1;

  if (r >= config::n_task_keys) {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  } else {
    key(r) = k.keys[1];
  }
}

void Context::do_read_region(ScopedReplySender & reply_sender,
                             Brand,
                             Message const & arg,
                             Keys &) {
  auto n = arg.d1;

  if (n < config::n_task_regions) {
    reply_sender.set_key(1, _body.memory_regions[n]);
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_write_region(ScopedReplySender & reply_sender,
                              Brand,
                              Message const & arg,
                              Keys & k) {
  auto n = arg.d1;

  if (n < config::n_task_regions) {
    _body.memory_regions[n] = k.keys[1];
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }

  if (current == this) apply_to_mpu();
}

void Context::do_make_runnable(ScopedReplySender &,
                               Brand,
                               Message const &,
                               Keys &) {
  make_runnable();
  pend_switch();
}

void Context::do_read_priority(ScopedReplySender & reply_sender,
                               Brand,
                               Message const &,
                               Keys &) {
  reply_sender.get_message().d1 = _body.priority;
}

void Context::do_write_priority(ScopedReplySender & reply_sender,
                                Brand,
                                Message const & arg,
                                Keys &) {
  auto priority = arg.d1;

  if (priority < config::n_priorities) {
    _body.priority = priority;

    if (_body.ctx_item.is_linked()) _body.ctx_item.reinsert();
    if (_body.sender_item.is_linked()) _body.sender_item.reinsert();
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_save_kernel_registers(ScopedReplySender & reply_sender,
                                       Brand,
                                       Message const & arg,
                                       Keys &) {
  uint32_t * dest = reinterpret_cast<uint32_t *>(arg.d1);

  for (unsigned i = 0; i < etl::array_count(_body.save.raw); ++i) {
    if (!ustore(&dest[i], _body.save.raw[i])) {
      reply_sender.get_message() = Message::failure(Exception::fault);
      return;
    }
  }
}

void Context::do_restore_kernel_registers(ScopedReplySender & reply_sender,
                                          Brand,
                                          Message const & arg,
                                          Keys &) {
  uint32_t const * src = reinterpret_cast<uint32_t const *>(arg.d1);

  for (unsigned i = 0; i < etl::array_count(_body.save.raw); ++i) {
    if (auto mval = uload(&src[i])) {
      _body.save.raw[i] = mval.ref();
    } else {
      reply_sender.get_message() = Message::failure(Exception::fault);
      return;
    }
  }
}

}  // namespace k
<commit_msg>Context: improve comments in on_delivery_accepted.<commit_after>#include "k/context.h"

#include "etl/array_count.h"
#include "etl/armv7m/mpu.h"
#include "etl/armv7m/types.h"

#include "common/abi_sizes.h"
#include "common/message.h"
#include "common/descriptor.h"

#include "k/memory.h"
#include "k/context_layout.h"
#include "k/object_table.h"
#include "k/registers.h"
#include "k/reply_gate.h"
#include "k/reply_sender.h"
#include "k/scheduler.h"
#include "k/unprivileged.h"

using etl::armv7m::Word;

namespace k {

template struct ObjectSubclassChecks<Context, kabi::context_size>;

static_assert(__builtin_offsetof(Context::Body, save) == 0,
    "Context::Body::save offset is wrong (should be zero, isn't)");

static_assert(K_CONTEXT_BODY_STACK_OFFSET ==
    __builtin_offsetof(Context::Body, save.named.stack),
    "K_CONTEXT_BODY_STACK_OFFSET is wrong");

/*******************************************************************************
 * Context-specific stuff
 */

Context::Context(Generation g, Body & body)
  : Object{g},
    _body(body) {
  body.ctx_item.owner = this;
  body.sender_item.owner = this;
}

void Context::nullify_exchanged_keys(unsigned preserved) {
  // Had to do this somewhere, this is as good a place as any.
  // (The fields in question are private, so this can't be at top level.)
  // (Putting it in the ctor hits the ill-defined non-trivial ctor rules.)
  static_assert(K_CONTEXT_BODY_OFFSET == __builtin_offsetof(Context, _body),
                "K_CONTEXT_BODY_OFFSET is wrong");

  // Right, actual implementation now:
  for (unsigned i = preserved; i < config::n_message_keys; ++i) {
    _body.keys[i] = Key::null();
  }
}

void Context::set_reply_gate(ReplyGate & g) {
  ETL_ASSERT(!g.is_bound());
  _body.reply_gate = &g;
  g.set_owner(this);
}

uint32_t Context::do_ipc(uint32_t stack, Descriptor d) {
  set_stack(stack);

  // Perform first phase of IPC.
  if (d.get_send_enabled()) {
    key(d.get_target()).deliver_from(this);
  } else if (d.get_receive_enabled()) {
    key(d.get_source()).get()->deliver_to(this);
  }
  // Note that if neither bit is set, we'll just return with the registers
  // unchanged.

  do_deferred_switch();

  return current->stack();
}

void Context::do_key_op(uint32_t sysnum, Descriptor d) {
  switch (sysnum) {
    case 1:  // Copy Key
      key(d.get_target()) = key(d.get_source());
      return;

    case 2:  // Discard Keys
      for (unsigned k = d.get_source(); k <= d.get_target(); ++k) {
        key(k) = Key::null();
      }
      return;

    default:
      // Bad sysnum used.  This should probably become a fault?
      return;
  }
}

void Context::complete_receive(BlockingSender * sender) {
  _body.save.sys = sender->on_blocked_delivery_accepted(get_message_keys());
}

void Context::complete_receive(Exception e, uint32_t param) {
  _body.save.sys = { Message::failure(e, param), 0 };
  nullify_exchanged_keys();
}

void Context::block_in_receive(List<Context> & list) {
  // TODO should we decide to permit non-blocking recieves... here's the spot.
  _body.ctx_item.unlink();
  list.insert(&_body.ctx_item);
  _body.state = State::receiving;

  pend_switch();
}

void Context::block_in_reply() {
  _body.ctx_item.unlink();
  _body.state = State::receiving;

  pend_switch();
}

void Context::complete_blocked_receive(Brand brand, Sender * sender) {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;
  _body.save.sys.brand = brand;

  pend_switch();

  _body.save.sys.m = sender->on_delivery_accepted(get_message_keys());
}

void Context::complete_blocked_receive(Exception e, uint32_t param) {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;

  pend_switch();

  complete_receive(e, param);
}

void Context::apply_to_mpu() {
  using etl::armv7m::mpu;

  for (unsigned i = 0; i < config::n_task_regions; ++i) {
    mpu.write_rnr(i);
    auto object = _body.memory_regions[i].get();
    auto region =
        object->get_region_for_brand(_body.memory_regions[i].get_brand());
    mpu.write_rbar(region.rbar);
    mpu.write_rasr(region.rasr);
  }
}

void Context::make_runnable() {
  switch (_body.state) {
    case State::sending:
      _body.sender_item.unlink();
      on_blocked_delivery_aborted();
      break;

    case State::receiving:
      _body.ctx_item.unlink();
      complete_blocked_receive(Exception::would_block);
      break;

    case State::stopped:
      runnable.insert(&_body.ctx_item);
      _body.state = State::runnable;
      break;

    case State::runnable:
      break;
  }
}

/*******************************************************************************
 * Implementation of Sender and BlockingSender
 */

Priority Context::get_priority() const {
  return _body.priority;
}

Message Context::on_delivery_accepted(Keys & k) {
  // We're either synchronously delivering our message, or have been found on a
  // block list and asked to deliver.

  // We assume that the descriptor is unchanged from when we sent.  If it is
  // not, it only affects us, since the recipient has been chosen.
  auto d = get_descriptor();

  // Make a copy of the message we're trying to send, sanitized.  We need to do
  // this because we may be about to receive into the same memory, below.
  auto m = _body.save.sys.m.sanitized();

  k.keys[0] = d.is_call() ? make_reply_key() : Key::null();
  for (unsigned ki = 1; ki < config::n_message_keys; ++ki) {
    k.keys[ki] = key(ki);
  }

  // Atomically transition to receive state if requested by the program.
  if (d.get_receive_enabled()) {
    // If we're calling, reuse the reply key we just minted:
    auto & source = d.is_call() ? k.keys[0]
                                : key(d.get_source());
    // And this is where our outgoing message would be overwritten; thus the
    // copy above.
    source.get()->deliver_to(this);
  }

  return m;
}

void Context::block_in_send(Brand brand, List<BlockingSender> & list) {
  ETL_ASSERT(this == current);

  if (get_descriptor().get_block()) {
    _body.saved_brand = brand;
    list.insert(&_body.sender_item);
    _body.ctx_item.unlink();
    _body.state = State::sending;

    pend_switch();
  } else {
    // Unprivileged code is unwilling to block for delivery.
    _body.save.sys = { Message::failure(Exception::would_block), 0 };
  }
}

ReceivedMessage Context::on_blocked_delivery_accepted(Keys & k) {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;

  pend_switch();
  return {
    .m = on_delivery_accepted(k),
    .brand = _body.saved_brand,
  };
}

void Context::on_blocked_delivery_aborted() {
  runnable.insert(&_body.ctx_item);
  _body.state = State::runnable;
  pend_switch();

  _body.save.sys = { Message::failure(Exception::would_block), 0 };
}

Key Context::make_reply_key() const {
  if (_body.reply_gate) {
    auto maybe_key = _body.reply_gate.ref()->make_key(0);
    if (maybe_key) return maybe_key.ref();
  }
  return Key::null();
}

/*******************************************************************************
 * Implementation of Context protocol.
 */

using IpcImpl = void (Context::*)(ScopedReplySender &,
                                  Brand,
                                  Message const &,
                                  Keys &);

void Context::deliver_from(Brand brand, Sender * sender) {
  Keys k;
  Message m = sender->on_delivery_accepted(k);

  static constexpr IpcImpl dispatch[] {
    &Context::do_read_register,
    &Context::do_write_register,
    &Context::do_read_key,
    &Context::do_write_key,
    &Context::do_read_region,
    &Context::do_write_region,
    &Context::do_make_runnable,
    &Context::do_read_priority,
    &Context::do_write_priority,
    &Context::do_save_kernel_registers,
    &Context::do_restore_kernel_registers,
  };
  if (m.d0.get_selector() < etl::array_count(dispatch)) {
    ScopedReplySender reply_sender{k.keys[0]};
    auto fn = dispatch[m.d0.get_selector()];
    (this->*fn)(reply_sender, brand, m, k);
  } else {
    do_badop(m, k);
  }
}

void Context::do_read_register(ScopedReplySender & reply_sender,
                               Brand,
                               Message const & arg,
                               Keys &) {
  if (arg.d1 < etl::array_count(_body.save.raw)) {
    reply_sender.get_message().d1 = _body.save.raw[arg.d1];
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_write_register(ScopedReplySender & reply_sender,
                                Brand,
                                Message const & arg,
                                Keys &) {
  if (arg.d1 < etl::array_count(_body.save.raw)) {
    _body.save.raw[arg.d1] = arg.d2;
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_read_key(ScopedReplySender & reply_sender,
                          Brand,
                          Message const & arg,
                          Keys &) {
  auto r = arg.d1;

  if (r >= config::n_task_keys) {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  } else {
    reply_sender.set_key(1, key(r));
  }
}

void Context::do_write_key(ScopedReplySender & reply_sender,
                           Brand,
                           Message const & arg,
                           Keys & k) {
  auto r = arg.d1;

  if (r >= config::n_task_keys) {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  } else {
    key(r) = k.keys[1];
  }
}

void Context::do_read_region(ScopedReplySender & reply_sender,
                             Brand,
                             Message const & arg,
                             Keys &) {
  auto n = arg.d1;

  if (n < config::n_task_regions) {
    reply_sender.set_key(1, _body.memory_regions[n]);
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_write_region(ScopedReplySender & reply_sender,
                              Brand,
                              Message const & arg,
                              Keys & k) {
  auto n = arg.d1;

  if (n < config::n_task_regions) {
    _body.memory_regions[n] = k.keys[1];
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }

  if (current == this) apply_to_mpu();
}

void Context::do_make_runnable(ScopedReplySender &,
                               Brand,
                               Message const &,
                               Keys &) {
  make_runnable();
  pend_switch();
}

void Context::do_read_priority(ScopedReplySender & reply_sender,
                               Brand,
                               Message const &,
                               Keys &) {
  reply_sender.get_message().d1 = _body.priority;
}

void Context::do_write_priority(ScopedReplySender & reply_sender,
                                Brand,
                                Message const & arg,
                                Keys &) {
  auto priority = arg.d1;

  if (priority < config::n_priorities) {
    _body.priority = priority;

    if (_body.ctx_item.is_linked()) _body.ctx_item.reinsert();
    if (_body.sender_item.is_linked()) _body.sender_item.reinsert();
  } else {
    reply_sender.get_message() = Message::failure(Exception::bad_argument);
  }
}

void Context::do_save_kernel_registers(ScopedReplySender & reply_sender,
                                       Brand,
                                       Message const & arg,
                                       Keys &) {
  uint32_t * dest = reinterpret_cast<uint32_t *>(arg.d1);

  for (unsigned i = 0; i < etl::array_count(_body.save.raw); ++i) {
    if (!ustore(&dest[i], _body.save.raw[i])) {
      reply_sender.get_message() = Message::failure(Exception::fault);
      return;
    }
  }
}

void Context::do_restore_kernel_registers(ScopedReplySender & reply_sender,
                                          Brand,
                                          Message const & arg,
                                          Keys &) {
  uint32_t const * src = reinterpret_cast<uint32_t const *>(arg.d1);

  for (unsigned i = 0; i < etl::array_count(_body.save.raw); ++i) {
    if (auto mval = uload(&src[i])) {
      _body.save.raw[i] = mval.ref();
    } else {
      reply_sender.get_message() = Message::failure(Exception::fault);
      return;
    }
  }
}

}  // namespace k
<|endoftext|>


<commit_before><commit_msg>correct  reading datum error<commit_after><|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* 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.                                                          *
*                                                                             *
* This program 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 General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/gui/PickHandler.h>

#include <sofa/component/collision/ComponentMouseInteraction.h>
#include <sofa/component/collision/RayContact.h>

#include <sofa/simulation/common/InitVisitor.h>
#include <sofa/simulation/common/DeleteVisitor.h>
#include <sofa/simulation/common/MechanicalVisitor.h>

#include <sofa/helper/Factory.inl>

#include <iostream>

namespace sofa
{
using namespace component::collision;
helper::Creator<ComponentMouseInteraction::ComponentMouseInteractionFactory,TComponentMouseInteraction<defaulttype::Vec3dTypes> > ComponentMouseInteractionVec3dClass ("MouseSpringVec3d",true);
helper::Creator<ComponentMouseInteraction::ComponentMouseInteractionFactory, TComponentMouseInteraction<defaulttype::Vec3fTypes> > ComponentMouseInteractionVec3fClass ("MouseSpringVec3f",true);

namespace gui
{

PickHandler::PickHandler():interactorInUse(false), mouseStatus(DEACTIVATED),mouseButton(NONE)
{
    operations[NONE] =
        operations[LEFT] =
                operations[MIDDLE] =
                        operations[RIGHT] = NULL;

    mouseNode = simulation::getSimulation()->newNode("Mouse");

    mouseContainer = new MouseContainer; mouseContainer->resize(1);
    mouseContainer->setName("MousePosition");
    mouseNode->addObject(mouseContainer);

    mouseCollision = new MouseCollisionModel;
    mouseCollision->setNbRay(1);
    mouseCollision->getRay(0).l() = 1000000;
    mouseCollision->setName("MouseCollisionModel");
    mouseNode->addObject(mouseCollision);

    mouseNode->init();
    mouseContainer->init();
    mouseCollision->init();

    typedef component::collision::ComponentMouseInteraction::ComponentMouseInteractionFactory MouseFactory;
    const MouseFactory *factory = MouseFactory::getInstance();
    for (MouseFactory::const_iterator it = factory->begin(); it != factory->end(); ++it)
    {
        instanceComponents.push_back(it->second->createInstance(NULL));
        instanceComponents.back()->init(mouseNode);
    }
    interaction = instanceComponents.back();
}

PickHandler::~PickHandler()
{
//       for (unsigned int i=0;i<instanceComponents.size();++i) delete instanceComponents[i];
}

void PickHandler::init()
{
    core::componentmodel::collision::Pipeline *pipeline;
    simulation::getSimulation()->getContext()->get(pipeline, core::objectmodel::BaseContext::SearchRoot);

    useCollisions = (pipeline != NULL);
}

void PickHandler::reset()
{
    activateRay(false);
    mouseButton = NONE;
    for (unsigned int i=0; i<instanceComponents.size(); ++i) instanceComponents[i]->reset();
}

void PickHandler::activateRay(bool act)
{
    if (interactorInUse && !act)
    {
        mouseNode->detachFromGraph();

        operations[LEFT]->end();
        operations[MIDDLE]->end();
        operations[RIGHT]->end();

        interaction->deactivate();

        interactorInUse=false;
    }
    else if (!interactorInUse && act)
    {
        Node *root = static_cast<Node*>(simulation::getSimulation()->getContext());
        root->addChild(mouseNode);
        interaction->activate();
        interactorInUse=true;
    }
}

bool PickHandler::needToCastRay()
{
    return !getInteraction()->mouseInteractor->isMouseAttached();
}

void PickHandler::setCompatibleInteractor()
{
    if (useCollisions)
    {
        if (!lastPicked.body ) return;

        if (interaction->isCompatible(lastPicked.body->getContext())) return;
        for (unsigned int i=0; i<instanceComponents.size(); ++i)
        {
            if (instanceComponents[i] != interaction &&
                instanceComponents[i]->isCompatible(lastPicked.body->getContext()))
            {
                interaction->deactivate();
                interaction = instanceComponents[i];
                interaction->activate();
            }
        }
    }
    else
    {
        if (!lastPicked.mstate) return;

        if (interaction->isCompatible(lastPicked.mstate->getContext())) return;
        for (unsigned int i=0; i<instanceComponents.size(); ++i)
        {
            if (instanceComponents[i] != interaction &&
                instanceComponents[i]->isCompatible(lastPicked.mstate->getContext()))
            {
                interaction->deactivate();
                interaction = instanceComponents[i];
                interaction->activate();
            }
        }
    }

}

void PickHandler::updateRay(const sofa::defaulttype::Vector3 &position,const sofa::defaulttype::Vector3 &orientation)
{
    if (!interactorInUse) return;
    mouseCollision->getRay(0).origin() = position+orientation*interaction->mouseInteractor->getDistanceFromMouse();
    mouseCollision->getRay(0).direction() = orientation;

    if (needToCastRay())
    {
        lastPicked=findCollision();
        setCompatibleInteractor();
        interaction->mouseInteractor->setMouseRayModel(mouseCollision);
        interaction->mouseInteractor->setBodyPicked(lastPicked);
    }

    if(mouseButton != NONE)
    {
        switch (mouseStatus)
        {
        case PRESSED:
        {
            operations[mouseButton]->start();
            mouseStatus=ACTIVATED;
            break;
        }
        case RELEASED:
        {
            operations[mouseButton]->end();
            mouseStatus=DEACTIVATED;
            break;
        }
        case ACTIVATED:
        {
            operations[mouseButton]->execution();
        }
        case DEACTIVATED:
        {
            operations[mouseButton]->wait();
        }
        }
    }
}

//Clear the node create, and destroy all its components
void PickHandler::handleMouseEvent(MOUSE_STATUS status, MOUSE_BUTTON button)
{
    if (!interaction) return;

    mouseButton=button;
    mouseStatus=status;
}

ComponentMouseInteraction *PickHandler::getInteraction()
{
    return interaction;
}

component::collision::BodyPicked PickHandler::findCollision()
{
    if (useCollisions) return findCollisionUsingPipeline();
    else               return findCollisionUsingBruteForce();
}

component::collision::BodyPicked PickHandler::findCollisionUsingPipeline()
{
    const defaulttype::Vector3& origin          = mouseCollision->getRay(0).origin();
    const defaulttype::Vector3& direction       = mouseCollision->getRay(0).direction();
    const double& maxLength                     = mouseCollision->getRay(0).l();

    BodyPicked result;
    const std::set< sofa::component::collision::BaseRayContact*> &contacts = mouseCollision->getContacts();
    for (std::set< sofa::component::collision::BaseRayContact*>::const_iterator it=contacts.begin(); it != contacts.end(); ++it)
    {

        const sofa::helper::vector<core::componentmodel::collision::DetectionOutput*>& output = (*it)->getDetectionOutputs();
        sofa::core::CollisionModel *modelInCollision;
        for (unsigned int i=0; i<output.size(); ++i)
        {

            if (output[i]->elem.first.getCollisionModel() == mouseCollision)
            {
                modelInCollision = output[i]->elem.second.getCollisionModel();
                if (!modelInCollision->isSimulated()) continue;

                const double d = (output[i]->point[1]-origin)*direction;
                if (d<0.0 || d>maxLength) continue;
                if (result.body == NULL || d < result.rayLength)
                {
                    result.body=modelInCollision;
                    result.indexCollisionElement = output[i]->elem.second.getIndex();
                    result.point = output[i]->point[1];
                    result.dist  = (output[i]->point[1]-output[i]->point[0]).norm();
                    result.rayLength  = d;
                }
            }
            else if (output[i]->elem.second.getCollisionModel() == mouseCollision)
            {
                modelInCollision = output[i]->elem.first.getCollisionModel();
                if (!modelInCollision->isSimulated()) continue;

                const double d = (output[i]->point[0]-origin)*direction;
                if (d<0.0 || d>maxLength) continue;
                if (result.body == NULL || d < result.rayLength)
                {
                    result.body=modelInCollision;
                    result.indexCollisionElement = output[i]->elem.first.getIndex();
                    result.point = output[i]->point[0];
                    result.dist  = (output[i]->point[1]-output[i]->point[0]).norm();
                    result.rayLength  = d;
                }
            }
        }
    }
    return result;
}

component::collision::BodyPicked PickHandler::findCollisionUsingBruteForce()
{
    const defaulttype::Vector3& origin          = mouseCollision->getRay(0).origin();
    const defaulttype::Vector3& direction       = mouseCollision->getRay(0).direction();
    const double& maxLength                     = mouseCollision->getRay(0).l();

    return findCollisionUsingBruteForce(origin, direction, maxLength);
}

component::collision::BodyPicked PickHandler::findCollisionUsingBruteForce(const defaulttype::Vector3& origin,
        const defaulttype::Vector3& direction,
        double maxLength)
{
    BodyPicked result;
    // Look for particles hit by this ray
    simulation::MechanicalPickParticlesVisitor picker(origin, direction, maxLength, 0);
    core::objectmodel::BaseNode* rootNode = dynamic_cast<core::objectmodel::BaseNode*>(sofa::simulation::getSimulation()->getContext());

    if (rootNode) picker.execute(rootNode->getContext());
    else std::cerr << "ERROR: root node not found." << std::endl;

    if (!picker.particles.empty())
    {
        core::componentmodel::behavior::BaseMechanicalState *mstate = picker.particles.begin()->second.first;
        result.mstate=mstate;
        result.indexCollisionElement = picker.particles.begin()->second.second;
        result.point[0] = mstate->getPX(result.indexCollisionElement);
        result.point[1] = mstate->getPY(result.indexCollisionElement);
        result.point[2] = mstate->getPZ(result.indexCollisionElement);
        result.dist =  0;
        result.rayLength = (result.point-origin)*direction;
    }
    return result;
}

}
}

<commit_msg>r5492/sofa-dev : FIX : Compilation with only SOFA_DOUBLE.<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* 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.                                                          *
*                                                                             *
* This program 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 General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include <sofa/gui/PickHandler.h>

#include <sofa/component/collision/ComponentMouseInteraction.h>
#include <sofa/component/collision/RayContact.h>

#include <sofa/simulation/common/InitVisitor.h>
#include <sofa/simulation/common/DeleteVisitor.h>
#include <sofa/simulation/common/MechanicalVisitor.h>

#include <sofa/helper/Factory.inl>

#include <iostream>

namespace sofa
{
using namespace component::collision;
#ifndef SOFA_FLOAT
helper::Creator<ComponentMouseInteraction::ComponentMouseInteractionFactory,TComponentMouseInteraction<defaulttype::Vec3dTypes> > ComponentMouseInteractionVec3dClass ("MouseSpringVec3d",true);
#endif
#ifndef SOFA_DOUBLE
helper::Creator<ComponentMouseInteraction::ComponentMouseInteractionFactory, TComponentMouseInteraction<defaulttype::Vec3fTypes> > ComponentMouseInteractionVec3fClass ("MouseSpringVec3f",true);
#endif

namespace gui
{

PickHandler::PickHandler():interactorInUse(false), mouseStatus(DEACTIVATED),mouseButton(NONE)
{
    operations[NONE] =
        operations[LEFT] =
                operations[MIDDLE] =
                        operations[RIGHT] = NULL;

    mouseNode = simulation::getSimulation()->newNode("Mouse");

    mouseContainer = new MouseContainer; mouseContainer->resize(1);
    mouseContainer->setName("MousePosition");
    mouseNode->addObject(mouseContainer);

    mouseCollision = new MouseCollisionModel;
    mouseCollision->setNbRay(1);
    mouseCollision->getRay(0).l() = 1000000;
    mouseCollision->setName("MouseCollisionModel");
    mouseNode->addObject(mouseCollision);

    mouseNode->init();
    mouseContainer->init();
    mouseCollision->init();

    typedef component::collision::ComponentMouseInteraction::ComponentMouseInteractionFactory MouseFactory;
    const MouseFactory *factory = MouseFactory::getInstance();
    for (MouseFactory::const_iterator it = factory->begin(); it != factory->end(); ++it)
    {
        instanceComponents.push_back(it->second->createInstance(NULL));
        instanceComponents.back()->init(mouseNode);
    }
    interaction = instanceComponents.back();
}

PickHandler::~PickHandler()
{
//       for (unsigned int i=0;i<instanceComponents.size();++i) delete instanceComponents[i];
}

void PickHandler::init()
{
    core::componentmodel::collision::Pipeline *pipeline;
    simulation::getSimulation()->getContext()->get(pipeline, core::objectmodel::BaseContext::SearchRoot);

    useCollisions = (pipeline != NULL);
}

void PickHandler::reset()
{
    activateRay(false);
    mouseButton = NONE;
    for (unsigned int i=0; i<instanceComponents.size(); ++i) instanceComponents[i]->reset();
}

void PickHandler::activateRay(bool act)
{
    if (interactorInUse && !act)
    {
        mouseNode->detachFromGraph();

        operations[LEFT]->end();
        operations[MIDDLE]->end();
        operations[RIGHT]->end();

        interaction->deactivate();

        interactorInUse=false;
    }
    else if (!interactorInUse && act)
    {
        Node *root = static_cast<Node*>(simulation::getSimulation()->getContext());
        root->addChild(mouseNode);
        interaction->activate();
        interactorInUse=true;
    }
}

bool PickHandler::needToCastRay()
{
    return !getInteraction()->mouseInteractor->isMouseAttached();
}

void PickHandler::setCompatibleInteractor()
{
    if (useCollisions)
    {
        if (!lastPicked.body ) return;

        if (interaction->isCompatible(lastPicked.body->getContext())) return;
        for (unsigned int i=0; i<instanceComponents.size(); ++i)
        {
            if (instanceComponents[i] != interaction &&
                instanceComponents[i]->isCompatible(lastPicked.body->getContext()))
            {
                interaction->deactivate();
                interaction = instanceComponents[i];
                interaction->activate();
            }
        }
    }
    else
    {
        if (!lastPicked.mstate) return;

        if (interaction->isCompatible(lastPicked.mstate->getContext())) return;
        for (unsigned int i=0; i<instanceComponents.size(); ++i)
        {
            if (instanceComponents[i] != interaction &&
                instanceComponents[i]->isCompatible(lastPicked.mstate->getContext()))
            {
                interaction->deactivate();
                interaction = instanceComponents[i];
                interaction->activate();
            }
        }
    }

}

void PickHandler::updateRay(const sofa::defaulttype::Vector3 &position,const sofa::defaulttype::Vector3 &orientation)
{
    if (!interactorInUse) return;
    mouseCollision->getRay(0).origin() = position+orientation*interaction->mouseInteractor->getDistanceFromMouse();
    mouseCollision->getRay(0).direction() = orientation;

    if (needToCastRay())
    {
        lastPicked=findCollision();
        setCompatibleInteractor();
        interaction->mouseInteractor->setMouseRayModel(mouseCollision);
        interaction->mouseInteractor->setBodyPicked(lastPicked);
    }

    if(mouseButton != NONE)
    {
        switch (mouseStatus)
        {
        case PRESSED:
        {
            operations[mouseButton]->start();
            mouseStatus=ACTIVATED;
            break;
        }
        case RELEASED:
        {
            operations[mouseButton]->end();
            mouseStatus=DEACTIVATED;
            break;
        }
        case ACTIVATED:
        {
            operations[mouseButton]->execution();
        }
        case DEACTIVATED:
        {
            operations[mouseButton]->wait();
        }
        }
    }
}

//Clear the node create, and destroy all its components
void PickHandler::handleMouseEvent(MOUSE_STATUS status, MOUSE_BUTTON button)
{
    if (!interaction) return;

    mouseButton=button;
    mouseStatus=status;
}

ComponentMouseInteraction *PickHandler::getInteraction()
{
    return interaction;
}

component::collision::BodyPicked PickHandler::findCollision()
{
    if (useCollisions) return findCollisionUsingPipeline();
    else               return findCollisionUsingBruteForce();
}

component::collision::BodyPicked PickHandler::findCollisionUsingPipeline()
{
    const defaulttype::Vector3& origin          = mouseCollision->getRay(0).origin();
    const defaulttype::Vector3& direction       = mouseCollision->getRay(0).direction();
    const double& maxLength                     = mouseCollision->getRay(0).l();

    BodyPicked result;
    const std::set< sofa::component::collision::BaseRayContact*> &contacts = mouseCollision->getContacts();
    for (std::set< sofa::component::collision::BaseRayContact*>::const_iterator it=contacts.begin(); it != contacts.end(); ++it)
    {

        const sofa::helper::vector<core::componentmodel::collision::DetectionOutput*>& output = (*it)->getDetectionOutputs();
        sofa::core::CollisionModel *modelInCollision;
        for (unsigned int i=0; i<output.size(); ++i)
        {

            if (output[i]->elem.first.getCollisionModel() == mouseCollision)
            {
                modelInCollision = output[i]->elem.second.getCollisionModel();
                if (!modelInCollision->isSimulated()) continue;

                const double d = (output[i]->point[1]-origin)*direction;
                if (d<0.0 || d>maxLength) continue;
                if (result.body == NULL || d < result.rayLength)
                {
                    result.body=modelInCollision;
                    result.indexCollisionElement = output[i]->elem.second.getIndex();
                    result.point = output[i]->point[1];
                    result.dist  = (output[i]->point[1]-output[i]->point[0]).norm();
                    result.rayLength  = d;
                }
            }
            else if (output[i]->elem.second.getCollisionModel() == mouseCollision)
            {
                modelInCollision = output[i]->elem.first.getCollisionModel();
                if (!modelInCollision->isSimulated()) continue;

                const double d = (output[i]->point[0]-origin)*direction;
                if (d<0.0 || d>maxLength) continue;
                if (result.body == NULL || d < result.rayLength)
                {
                    result.body=modelInCollision;
                    result.indexCollisionElement = output[i]->elem.first.getIndex();
                    result.point = output[i]->point[0];
                    result.dist  = (output[i]->point[1]-output[i]->point[0]).norm();
                    result.rayLength  = d;
                }
            }
        }
    }
    return result;
}

component::collision::BodyPicked PickHandler::findCollisionUsingBruteForce()
{
    const defaulttype::Vector3& origin          = mouseCollision->getRay(0).origin();
    const defaulttype::Vector3& direction       = mouseCollision->getRay(0).direction();
    const double& maxLength                     = mouseCollision->getRay(0).l();

    return findCollisionUsingBruteForce(origin, direction, maxLength);
}

component::collision::BodyPicked PickHandler::findCollisionUsingBruteForce(const defaulttype::Vector3& origin,
        const defaulttype::Vector3& direction,
        double maxLength)
{
    BodyPicked result;
    // Look for particles hit by this ray
    simulation::MechanicalPickParticlesVisitor picker(origin, direction, maxLength, 0);
    core::objectmodel::BaseNode* rootNode = dynamic_cast<core::objectmodel::BaseNode*>(sofa::simulation::getSimulation()->getContext());

    if (rootNode) picker.execute(rootNode->getContext());
    else std::cerr << "ERROR: root node not found." << std::endl;

    if (!picker.particles.empty())
    {
        core::componentmodel::behavior::BaseMechanicalState *mstate = picker.particles.begin()->second.first;
        result.mstate=mstate;
        result.indexCollisionElement = picker.particles.begin()->second.second;
        result.point[0] = mstate->getPX(result.indexCollisionElement);
        result.point[1] = mstate->getPY(result.indexCollisionElement);
        result.point[2] = mstate->getPZ(result.indexCollisionElement);
        result.dist =  0;
        result.rayLength = (result.point-origin)*direction;
    }
    return result;
}

}
}

<|endoftext|>


<commit_before>#include "dbreader.h"

#define DEBUG if (0) qDebug() << __PRETTY_FUNCTION__

DbReader::DbReader(QObject *parent)
    : QObject(parent), m_stop(false)
{
    qRegisterMetaType<QList<QSqlRecord> >();
    qRegisterMetaType<QSqlDatabase>();
    qRegisterMetaType<QSqlQuery>();
    qRegisterMetaType<DbReader *>();
    qRegisterMetaType<void *>();
}

DbReader::~DbReader()
{
    QSqlDatabase::removeDatabase(m_db.connectionName());
}

void DbReader::stop()
{
    m_stop = true;
}

void DbReader::initialize(const QSqlDatabase &db)
{
    m_db = QSqlDatabase::cloneDatabase(db, QUuid::createUuid().toString());
    if (!m_db.open())
        qFatal("Erorr opening database: %s", qPrintable(m_db.lastError().text()));
}

void DbReader::execute(const QSqlQuery &q, void *userData)
{
    QSqlQuery query(q);
    query.setForwardOnly(true);
    if (!query.exec())
        qFatal("Error executing query: %s", qPrintable(query.lastQuery()));

    QList<QSqlRecord> data = readRecords(query);
    DEBUG << "Read " << data.count() << "records";

    if (!m_stop)
        emit dataReady(this, data, userData);
}

QList<QSqlRecord> DbReader::readRecords(QSqlQuery &query)
{
    QList<QSqlRecord> data;
    while (query.next() && !m_stop) {
        data.append(query.record());
    }
    return data;
}

<commit_msg>Clear database variable, to avoid warning when closing the connection<commit_after>#include "dbreader.h"

#define DEBUG if (0) qDebug() << __PRETTY_FUNCTION__

DbReader::DbReader(QObject *parent)
    : QObject(parent), m_stop(false)
{
    qRegisterMetaType<QList<QSqlRecord> >();
    qRegisterMetaType<QSqlDatabase>();
    qRegisterMetaType<QSqlQuery>();
    qRegisterMetaType<DbReader *>();
    qRegisterMetaType<void *>();
}

DbReader::~DbReader()
{
    m_db = QSqlDatabase();
    QSqlDatabase::removeDatabase(m_db.connectionName());
}

void DbReader::stop()
{
    m_stop = true;
}

void DbReader::initialize(const QSqlDatabase &db)
{
    m_db = QSqlDatabase::cloneDatabase(db, QUuid::createUuid().toString());
    if (!m_db.open())
        qFatal("Erorr opening database: %s", qPrintable(m_db.lastError().text()));
}

void DbReader::execute(const QSqlQuery &q, void *userData)
{
    QSqlQuery query(q);
    query.setForwardOnly(true);
    if (!query.exec())
        qFatal("Error executing query: %s", qPrintable(query.lastQuery()));

    QList<QSqlRecord> data = readRecords(query);
    DEBUG << "Read " << data.count() << "records";

    if (!m_stop)
        emit dataReady(this, data, userData);
}

QList<QSqlRecord> DbReader::readRecords(QSqlQuery &query)
{
    QList<QSqlRecord> data;
    while (query.next() && !m_stop) {
        data.append(query.record());
    }
    return data;
}

<|endoftext|>


<commit_before><commit_msg>Set port for floodechos subrequests<commit_after><|endoftext|>


<commit_before>/******************************************************************************\
* File:          process.cpp
* Purpose:       Implementation of class 'wxExProcess'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/regex.h>
#include <wx/tokenzr.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/configdlg.h>
#include <wx/extension/log.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf
#include <wx/extension/report/process.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/listitem.h>
#include <wx/extension/report/listview.h>

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxString wxExProcess::m_Command;
wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess(
  wxExFrameWithHistory* frame,
  const wxString& command)
  : wxProcess(NULL, -1)
  , m_Frame(frame)
  , m_ListView(NULL)
  , m_Timer(this)
{
  if (!command.empty())
  {
    m_Command = command;
  }

  Redirect();
}

bool wxExProcess::CheckInput()
{
  if (m_ListView == NULL)
  {
    return false;
  }

  bool hasInput = false;

  // This assumes that the output is always line buffered.
  wxString line;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());
    line << tis.ReadLine();
    hasInput = true;
  }
  else if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());
    line << tis.ReadLine();
    hasInput = true;
  }

  if (hasInput && !line.empty())
  {
    wxString lineno;
    wxString path;

    // Check on error in php script output.
    const wxRegEx regex(".*in \\(.*\\) on line \\(.*\\)", wxRE_ADVANCED);

    if (regex.Matches(line))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        path = line.substr(start, len);
      }

      if (regex.GetMatch(&start, &len, 2))
      {
        lineno = line.substr(start, len);
      }
    }
    else
    {
      // Check on error in gcc output (and some others).
      wxStringTokenizer tkz(line, ':');
      path = tkz.GetNextToken();

      if (tkz.HasMoreTokens())
      {
        const wxString number = tkz.GetNextToken();
        if (atoi(number.c_str()) != 0) lineno = number;
      }
    }

    wxFileName fn(path);

    fn.Normalize();

    if (fn.FileExists())
    {
      wxExListItem item(m_ListView, fn);
      item.Insert();
      item.SetItem(_("Line"), line);
      item.SetItem(_("Line No"), lineno);
    }
    else
    {
      m_ListView->InsertItem(m_ListView->GetItemCount(), line, -1);
    }

    // If nothing selected, then ensure last line is visible.
    // Otherwise you are busy inspecting some line, and
    // it would be irritating to get it out of view.
    if (m_ListView->GetSelectedItemCount() == 0)
    {
      m_ListView->EnsureVisible(m_ListView->GetItemCount() - 1);
    }

#if wxUSE_STATUSBAR
    m_ListView->UpdateStatusBar();
#endif
  }

  return hasInput;
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString));

  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1000));

  const auto result = wxExConfigDialog(parent,
    v,
    title).ShowModal();

  if (result == wxID_OK)
  {
    m_Command = wxExConfigFirstOf(_("Process"));
  }

  return result;
}

long wxExProcess::Execute()
{
  if (m_Command.empty())
  {
    if (ConfigDialog(m_ListView) == wxID_CANCEL)
    {
      return 0;
    }
  }

  wxString cwd;
  const wxString dir = wxExConfigFirstOf(m_WorkingDirKey);

  if (!dir.empty())
  {
    cwd = wxGetCwd();
    if (!wxSetWorkingDirectory(dir))
    {
      wxLogError(_("Cannot set working directory"));
      return 0;
    }
  }

  m_ListView = m_Frame->Activate(wxExListViewStandard::LIST_PROCESS);

  if (m_ListView == NULL)
  {
    // Only show a message, and continue,
    // easier for testing.
    wxLogMessage(_("No listview to collect output"));
  }

  const long pid = wxExecute(m_Command, wxEXEC_ASYNC, this);

  if (pid > 0)
  {
    SetPid(pid);

#if wxUSE_STATUSBAR
    wxExFrame::StatusText(m_Command);
#endif
    wxExLog::Get()->Log(m_Command);

    m_Timer.Start(1000); // each 1000 milliseconds
  }
  else
  {
    wxLogError(_("Cannot execute") + ": " + m_Command);
  }

  if (!cwd.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  return pid;
}

bool wxExProcess::IsRunning() const
{
  if (GetPid() < 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  m_Timer.Stop();

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Stopped"));
#endif

  DeletePendingEvents();

  delete this;

  return wxProcess::Kill(GetPid(), sig);
}

void wxExProcess::OnTerminate(
  int WXUNUSED(pid),
  int WXUNUSED(status))
{
  m_Timer.Stop();

  // Collect remaining input.
  while (CheckInput())
  {
    // Do nothing.
  }

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Ready"));
#endif

  wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_TERMINATED_PROCESS);
  wxPostEvent(wxTheApp->GetTopWindow(), event);
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  while (CheckInput())
  {
    // Do nothing.
  }
}
<commit_msg>do not delete process any more<commit_after>/******************************************************************************\
* File:          process.cpp
* Purpose:       Implementation of class 'wxExProcess'
* Author:        Anton van Wezenbeek
* RCS-ID:        $Id$
*
* Copyright (c) 1998-2009 Anton van Wezenbeek
* All rights are reserved. Reproduction in whole or part is prohibited
* without the written consent of the copyright owner.
\******************************************************************************/

#include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/wx.h>
#endif
#include <wx/regex.h>
#include <wx/tokenzr.h>
#include <wx/txtstrm.h> // for wxTextInputStream
#include <wx/extension/configdlg.h>
#include <wx/extension/log.h>
#include <wx/extension/util.h> // for wxExConfigFirstOf
#include <wx/extension/report/process.h>
#include <wx/extension/report/defs.h>
#include <wx/extension/report/frame.h>
#include <wx/extension/report/listitem.h>
#include <wx/extension/report/listview.h>

BEGIN_EVENT_TABLE(wxExProcess, wxProcess)
  EVT_TIMER(-1, wxExProcess::OnTimer)
END_EVENT_TABLE()

wxString wxExProcess::m_Command;
wxString wxExProcess::m_WorkingDirKey = _("Process folder");

wxExProcess::wxExProcess(
  wxExFrameWithHistory* frame,
  const wxString& command)
  : wxProcess(NULL, -1)
  , m_Frame(frame)
  , m_ListView(NULL)
  , m_Timer(this)
{
  if (!command.empty())
  {
    m_Command = command;
  }

  Redirect();
}

bool wxExProcess::CheckInput()
{
  if (m_ListView == NULL)
  {
    return false;
  }

  bool hasInput = false;

  // This assumes that the output is always line buffered.
  wxString line;

  if (IsInputAvailable())
  {
    wxTextInputStream tis(*GetInputStream());
    line << tis.ReadLine();
    hasInput = true;
  }
  else if (IsErrorAvailable())
  {
    wxTextInputStream tis(*GetErrorStream());
    line << tis.ReadLine();
    hasInput = true;
  }

  if (hasInput && !line.empty())
  {
    wxString lineno;
    wxString path;

    // Check on error in php script output.
    const wxRegEx regex(".*in \\(.*\\) on line \\(.*\\)", wxRE_ADVANCED);

    if (regex.Matches(line))
    {
      size_t start, len;

      if (regex.GetMatch(&start, &len, 1))
      {
        path = line.substr(start, len);
      }

      if (regex.GetMatch(&start, &len, 2))
      {
        lineno = line.substr(start, len);
      }
    }
    else
    {
      // Check on error in gcc output (and some others).
      wxStringTokenizer tkz(line, ':');
      path = tkz.GetNextToken();

      if (tkz.HasMoreTokens())
      {
        const wxString number = tkz.GetNextToken();
        if (atoi(number.c_str()) != 0) lineno = number;
      }
    }

    wxFileName fn(path);

    fn.Normalize();

    if (fn.FileExists())
    {
      wxExListItem item(m_ListView, fn);
      item.Insert();
      item.SetItem(_("Line"), line);
      item.SetItem(_("Line No"), lineno);
    }
    else
    {
      m_ListView->InsertItem(m_ListView->GetItemCount(), line, -1);
    }

    // If nothing selected, then ensure last line is visible.
    // Otherwise you are busy inspecting some line, and
    // it would be irritating to get it out of view.
    if (m_ListView->GetSelectedItemCount() == 0)
    {
      m_ListView->EnsureVisible(m_ListView->GetItemCount() - 1);
    }

#if wxUSE_STATUSBAR
    m_ListView->UpdateStatusBar();
#endif
  }

  return hasInput;
}

int wxExProcess::ConfigDialog(
  wxWindow* parent,
  const wxString& title)
{
  std::vector<wxExConfigItem> v;

  v.push_back(wxExConfigItem(
    _("Process"),
    CONFIG_COMBOBOX,
    wxEmptyString));

  v.push_back(wxExConfigItem(
    m_WorkingDirKey,
    CONFIG_COMBOBOXDIR,
    wxEmptyString,
    true,
    1000));

  const auto result = wxExConfigDialog(parent,
    v,
    title).ShowModal();

  if (result == wxID_OK)
  {
    m_Command = wxExConfigFirstOf(_("Process"));
  }

  return result;
}

long wxExProcess::Execute()
{
  if (m_Command.empty())
  {
    if (ConfigDialog(m_ListView) == wxID_CANCEL)
    {
      return 0;
    }
  }

  wxString cwd;
  const wxString dir = wxExConfigFirstOf(m_WorkingDirKey);

  if (!dir.empty())
  {
    cwd = wxGetCwd();
    if (!wxSetWorkingDirectory(dir))
    {
      wxLogError(_("Cannot set working directory"));
      return 0;
    }
  }

  m_ListView = m_Frame->Activate(wxExListViewStandard::LIST_PROCESS);

  if (m_ListView == NULL)
  {
    // Only show a message, and continue,
    // easier for testing.
    wxLogMessage(_("No listview to collect output"));
  }

  const long pid = wxExecute(m_Command, wxEXEC_ASYNC, this);

  if (pid > 0)
  {
    SetPid(pid);

#if wxUSE_STATUSBAR
    wxExFrame::StatusText(m_Command);
#endif
    wxExLog::Get()->Log(m_Command);

    m_Timer.Start(1000); // each 1000 milliseconds
  }
  else
  {
    wxLogError(_("Cannot execute") + ": " + m_Command);
  }

  if (!cwd.empty())
  {
    wxSetWorkingDirectory(cwd);
  }

  return pid;
}

bool wxExProcess::IsRunning() const
{
  if (GetPid() < 0)
  {
    return false;
  }

  return Exists(GetPid());
}

wxKillError wxExProcess::Kill(wxSignal sig)
{
  if (!IsRunning())
  {
    return wxKILL_NO_PROCESS;
  }

  m_Timer.Stop();

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Stopped"));
#endif

  DeletePendingEvents();

  return wxProcess::Kill(GetPid(), sig);
}

void wxExProcess::OnTerminate(
  int WXUNUSED(pid),
  int WXUNUSED(status))
{
  m_Timer.Stop();

  // Collect remaining input.
  while (CheckInput())
  {
    // Do nothing.
  }

#if wxUSE_STATUSBAR
  wxExFrame::StatusText(_("Ready"));
#endif

  wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID_TERMINATED_PROCESS);
  wxPostEvent(wxTheApp->GetTopWindow(), event);
}

void wxExProcess::OnTimer(wxTimerEvent& event)
{
  while (CheckInput())
  {
    // Do nothing.
  }
}
<|endoftext|>


<commit_before>/*
  This file is part of the PhantomJS project from Ofi Labs.

  Copyright (C) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>

  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 <organization> 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 <COPYRIGHT HOLDER> 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 <QtGui>
#include <QtWebKit>
#include <iostream>

#if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
#error Use Qt 4.5 or later version
#endif

#define PHANTOMJS_VERSION_MAJOR  1
#define PHANTOMJS_VERSION_MINOR  1
#define PHANTOMJS_VERSION_PATCH  0
#define PHANTOMJS_VERSION_STRING "1.1.0"

class WebPage: public QWebPage
{
    Q_OBJECT
public:
    WebPage(QObject *parent = 0);

public slots:
    bool shouldInterruptJavaScript();

protected:
    void javaScriptAlert(QWebFrame *originatingFrame, const QString &msg);
    void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
    QString userAgentForUrl(const QUrl &url) const;

private:
    QString m_userAgent;
    friend class Phantom;
};

WebPage::WebPage(QObject *parent)
    : QWebPage(parent)
{
    m_userAgent = QWebPage::userAgentForUrl(QUrl());
}

void WebPage::javaScriptAlert(QWebFrame *originatingFrame, const QString &msg)
{
    Q_UNUSED(originatingFrame);
    std::cout << "JavaScript alert: " << qPrintable(msg) << std::endl;
}

void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID)
{
    if (!sourceID.isEmpty())
        std::cout << qPrintable(sourceID) << ":" << lineNumber << " ";
    std::cout << qPrintable(message) << std::endl;
}

bool WebPage::shouldInterruptJavaScript()
{
    QApplication::processEvents(QEventLoop::AllEvents, 42);
    return false;
}

QString WebPage::userAgentForUrl(const QUrl &url) const
{
    Q_UNUSED(url);
    return m_userAgent;
}

class Phantom: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QStringList args READ args)
    Q_PROPERTY(QString content READ content WRITE setContent)
    Q_PROPERTY(QString loadStatus READ loadStatus)
    Q_PROPERTY(QString state READ state WRITE setState)
    Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent)
    Q_PROPERTY(QVariantMap version READ version)
    Q_PROPERTY(QVariantMap viewportSize READ viewportSize WRITE setViewportSize)

public:
    Phantom(QObject *parent = 0);

    QStringList args() const;

    QString content() const;
    void setContent(const QString &content);

    void execute(const QString &fileName);
    int returnValue() const;

    QString loadStatus() const;

    void setState(const QString &value);
    QString state() const;

    void setUserAgent(const QString &ua);
    QString userAgent() const;

    QVariantMap version() const;

    void setViewportSize(const QVariantMap &size);
    QVariantMap viewportSize() const;

public slots:
    void exit(int code = 0);
    void open(const QString &address);
    bool render(const QString &fileName);
    void sleep(int ms);

private slots:
    void inject();
    void finish(bool);

private:
    QStringList m_args;
    QString m_loadStatus;
    WebPage m_page;
    int m_returnValue;
    QString m_script;
    QString m_state;
};

Phantom::Phantom(QObject *parent)
    : QObject(parent)
    , m_returnValue(0)
{
    QPalette palette = m_page.palette();
    palette.setBrush(QPalette::Base, Qt::transparent);
    m_page.setPalette(palette);

    // first argument: program name (phantomjs)
    // second argument: script name
    m_args = QApplication::arguments();
    m_args.removeFirst();
    m_args.removeFirst();

    connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), SLOT(inject()));
    connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool)));

    m_page.settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
    m_page.settings()->setOfflineStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));

#if QT_VERSION < QT_VERSION_CHECK(4, 6, 0)
    m_page.settings()->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, true);
#else
    m_page.settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, true);
    m_page.settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
    m_page.settings()->setLocalStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
#endif

    // Ensure we have document.body.
    m_page.mainFrame()->setHtml("");

    m_page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    m_page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
}

QStringList Phantom::args() const
{
     return m_args;
}

QString Phantom::content() const
{
    return m_page.mainFrame()->toHtml();
}

void Phantom::setContent(const QString &content)
{
    m_page.mainFrame()->setHtml(content);
}

void Phantom::execute(const QString &fileName)
{
    QFile file;
    file.setFileName(fileName);
    if (!file.open(QFile::ReadOnly)) {
        std::cerr << "Can't open " << qPrintable(fileName) << std::endl << std::endl;
        exit(1);
        return;
    }
    m_script =  QString::fromUtf8(file.readAll());
    file.close();

    m_page.mainFrame()->evaluateJavaScript(m_script);
}

void Phantom::exit(int code)
{
    m_returnValue = code;
    disconnect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool)));
    QTimer::singleShot(0, qApp, SLOT(quit()));
}

void Phantom::finish(bool success)
{
    m_loadStatus = success ? "success" : "fail";
    m_page.mainFrame()->evaluateJavaScript(m_script);
}

void Phantom::inject()
{
    m_page.mainFrame()->addToJavaScriptWindowObject("phantom", this);
}

QString Phantom::loadStatus() const
{
    return m_loadStatus;
}

void Phantom::open(const QString &address)
{
    m_page.triggerAction(QWebPage::Stop);
    m_loadStatus = "loading";
    m_page.mainFrame()->setUrl(address);
}

bool Phantom::render(const QString &fileName)
{
    QFileInfo fileInfo(fileName);
    QDir dir;
    dir.mkpath(fileInfo.absolutePath());

    if (fileName.toLower().endsWith(".pdf")) {
        QPrinter printer;
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(fileName);
        m_page.mainFrame()->print(&printer);
        return true;
    }

    QSize viewportSize = m_page.viewportSize();
    QSize pageSize = m_page.mainFrame()->contentsSize();
    if (pageSize.isEmpty())
        return false;

    QImage buffer(pageSize, QImage::Format_ARGB32);
    buffer.fill(qRgba(255, 255, 255, 0));
    QPainter p(&buffer);
    p.setRenderHint(QPainter::Antialiasing, true);
    p.setRenderHint(QPainter::TextAntialiasing, true);
    p.setRenderHint(QPainter::SmoothPixmapTransform, true);
    m_page.setViewportSize(pageSize);
    m_page.mainFrame()->render(&p);
    p.end();
    m_page.setViewportSize(viewportSize);
    return buffer.save(fileName);
}

int Phantom::returnValue() const
{
    return m_returnValue;
}

void Phantom::sleep(int ms)
{
    QTime startTime = QTime::currentTime();
    while (true) {
        QApplication::processEvents(QEventLoop::AllEvents, 25);
        if (startTime.msecsTo(QTime::currentTime()) > ms)
            break;
    }
}

void Phantom::setState(const QString &value)
{
    m_state = value;
}

QString Phantom::state() const
{
    return m_state;
}

void Phantom::setUserAgent(const QString &ua)
{
    m_page.m_userAgent = ua;
}

QString Phantom::userAgent() const
{
    return m_page.m_userAgent;
}

QVariantMap Phantom::version() const
{
    QVariantMap result;
    result["major"] = PHANTOMJS_VERSION_MAJOR;
    result["minor"] = PHANTOMJS_VERSION_MINOR;
    result["patch"] = PHANTOMJS_VERSION_PATCH;
    return result;
}

void Phantom::setViewportSize(const QVariantMap &size)
{
    int w = size.value("width").toInt();
    int h = size.value("height").toInt();
    if (w > 0 && h > 0)
        m_page.setViewportSize(QSize(w, h));
}

QVariantMap Phantom::viewportSize() const
{
    QVariantMap result;
    QSize size = m_page.viewportSize();
    result["width"] = size.width();
    result["height"] = size.height();
    return result;
}

#include "phantomjs.moc"

int main(int argc, char** argv)
{
    if (argc < 2) {
        std::cerr << "phantomjs script.js" << std::endl << std::endl;
        return 1;
    }

    QNetworkProxyFactory::setUseSystemConfiguration(true);

    QApplication app(argc, argv);

    app.setWindowIcon(QIcon(":/phantomjs-icon.png"));
    app.setApplicationName("PhantomJS");
    app.setOrganizationName("Ofi Labs");
    app.setOrganizationDomain("www.ofilabs.com");
    app.setApplicationVersion(PHANTOMJS_VERSION_STRING);

    Phantom phantom;
    phantom.execute(QString::fromLocal8Bit(argv[1]));
    app.exec();
    return phantom.returnValue();
}
<commit_msg>Make it compile with Qt 4.6.<commit_after>/*
  This file is part of the PhantomJS project from Ofi Labs.

  Copyright (C) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>

  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 <organization> 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 <COPYRIGHT HOLDER> 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 <QtGui>
#include <QtWebKit>
#include <iostream>

#if QT_VERSION < QT_VERSION_CHECK(4, 5, 0)
#error Use Qt 4.5 or later version
#endif

#define PHANTOMJS_VERSION_MAJOR  1
#define PHANTOMJS_VERSION_MINOR  1
#define PHANTOMJS_VERSION_PATCH  0
#define PHANTOMJS_VERSION_STRING "1.1.0"

class WebPage: public QWebPage
{
    Q_OBJECT
public:
    WebPage(QObject *parent = 0);

public slots:
    bool shouldInterruptJavaScript();

protected:
    void javaScriptAlert(QWebFrame *originatingFrame, const QString &msg);
    void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
    QString userAgentForUrl(const QUrl &url) const;

private:
    QString m_userAgent;
    friend class Phantom;
};

WebPage::WebPage(QObject *parent)
    : QWebPage(parent)
{
    m_userAgent = QWebPage::userAgentForUrl(QUrl());
}

void WebPage::javaScriptAlert(QWebFrame *originatingFrame, const QString &msg)
{
    Q_UNUSED(originatingFrame);
    std::cout << "JavaScript alert: " << qPrintable(msg) << std::endl;
}

void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID)
{
    if (!sourceID.isEmpty())
        std::cout << qPrintable(sourceID) << ":" << lineNumber << " ";
    std::cout << qPrintable(message) << std::endl;
}

bool WebPage::shouldInterruptJavaScript()
{
    QApplication::processEvents(QEventLoop::AllEvents, 42);
    return false;
}

QString WebPage::userAgentForUrl(const QUrl &url) const
{
    Q_UNUSED(url);
    return m_userAgent;
}

class Phantom: public QObject
{
    Q_OBJECT
    Q_PROPERTY(QStringList args READ args)
    Q_PROPERTY(QString content READ content WRITE setContent)
    Q_PROPERTY(QString loadStatus READ loadStatus)
    Q_PROPERTY(QString state READ state WRITE setState)
    Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent)
    Q_PROPERTY(QVariantMap version READ version)
    Q_PROPERTY(QVariantMap viewportSize READ viewportSize WRITE setViewportSize)

public:
    Phantom(QObject *parent = 0);

    QStringList args() const;

    QString content() const;
    void setContent(const QString &content);

    void execute(const QString &fileName);
    int returnValue() const;

    QString loadStatus() const;

    void setState(const QString &value);
    QString state() const;

    void setUserAgent(const QString &ua);
    QString userAgent() const;

    QVariantMap version() const;

    void setViewportSize(const QVariantMap &size);
    QVariantMap viewportSize() const;

public slots:
    void exit(int code = 0);
    void open(const QString &address);
    bool render(const QString &fileName);
    void sleep(int ms);

private slots:
    void inject();
    void finish(bool);

private:
    QStringList m_args;
    QString m_loadStatus;
    WebPage m_page;
    int m_returnValue;
    QString m_script;
    QString m_state;
};

Phantom::Phantom(QObject *parent)
    : QObject(parent)
    , m_returnValue(0)
{
    QPalette palette = m_page.palette();
    palette.setBrush(QPalette::Base, Qt::transparent);
    m_page.setPalette(palette);

    // first argument: program name (phantomjs)
    // second argument: script name
    m_args = QApplication::arguments();
    m_args.removeFirst();
    m_args.removeFirst();

    connect(m_page.mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), SLOT(inject()));
    connect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool)));

    m_page.settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, true);
    m_page.settings()->setOfflineStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));

    m_page.settings()->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, true);

#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
    m_page.settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, true);
    m_page.settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
    m_page.settings()->setLocalStoragePath(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
#endif

    // Ensure we have document.body.
    m_page.mainFrame()->setHtml("");

    m_page.mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAlwaysOff);
    m_page.mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAlwaysOff);
}

QStringList Phantom::args() const
{
     return m_args;
}

QString Phantom::content() const
{
    return m_page.mainFrame()->toHtml();
}

void Phantom::setContent(const QString &content)
{
    m_page.mainFrame()->setHtml(content);
}

void Phantom::execute(const QString &fileName)
{
    QFile file;
    file.setFileName(fileName);
    if (!file.open(QFile::ReadOnly)) {
        std::cerr << "Can't open " << qPrintable(fileName) << std::endl << std::endl;
        exit(1);
        return;
    }
    m_script =  QString::fromUtf8(file.readAll());
    file.close();

    m_page.mainFrame()->evaluateJavaScript(m_script);
}

void Phantom::exit(int code)
{
    m_returnValue = code;
    disconnect(&m_page, SIGNAL(loadFinished(bool)), this, SLOT(finish(bool)));
    QTimer::singleShot(0, qApp, SLOT(quit()));
}

void Phantom::finish(bool success)
{
    m_loadStatus = success ? "success" : "fail";
    m_page.mainFrame()->evaluateJavaScript(m_script);
}

void Phantom::inject()
{
    m_page.mainFrame()->addToJavaScriptWindowObject("phantom", this);
}

QString Phantom::loadStatus() const
{
    return m_loadStatus;
}

void Phantom::open(const QString &address)
{
    m_page.triggerAction(QWebPage::Stop);
    m_loadStatus = "loading";
    m_page.mainFrame()->setUrl(address);
}

bool Phantom::render(const QString &fileName)
{
    QFileInfo fileInfo(fileName);
    QDir dir;
    dir.mkpath(fileInfo.absolutePath());

    if (fileName.toLower().endsWith(".pdf")) {
        QPrinter printer;
        printer.setOutputFormat(QPrinter::PdfFormat);
        printer.setOutputFileName(fileName);
        m_page.mainFrame()->print(&printer);
        return true;
    }

    QSize viewportSize = m_page.viewportSize();
    QSize pageSize = m_page.mainFrame()->contentsSize();
    if (pageSize.isEmpty())
        return false;

    QImage buffer(pageSize, QImage::Format_ARGB32);
    buffer.fill(qRgba(255, 255, 255, 0));
    QPainter p(&buffer);
    p.setRenderHint(QPainter::Antialiasing, true);
    p.setRenderHint(QPainter::TextAntialiasing, true);
    p.setRenderHint(QPainter::SmoothPixmapTransform, true);
    m_page.setViewportSize(pageSize);
    m_page.mainFrame()->render(&p);
    p.end();
    m_page.setViewportSize(viewportSize);
    return buffer.save(fileName);
}

int Phantom::returnValue() const
{
    return m_returnValue;
}

void Phantom::sleep(int ms)
{
    QTime startTime = QTime::currentTime();
    while (true) {
        QApplication::processEvents(QEventLoop::AllEvents, 25);
        if (startTime.msecsTo(QTime::currentTime()) > ms)
            break;
    }
}

void Phantom::setState(const QString &value)
{
    m_state = value;
}

QString Phantom::state() const
{
    return m_state;
}

void Phantom::setUserAgent(const QString &ua)
{
    m_page.m_userAgent = ua;
}

QString Phantom::userAgent() const
{
    return m_page.m_userAgent;
}

QVariantMap Phantom::version() const
{
    QVariantMap result;
    result["major"] = PHANTOMJS_VERSION_MAJOR;
    result["minor"] = PHANTOMJS_VERSION_MINOR;
    result["patch"] = PHANTOMJS_VERSION_PATCH;
    return result;
}

void Phantom::setViewportSize(const QVariantMap &size)
{
    int w = size.value("width").toInt();
    int h = size.value("height").toInt();
    if (w > 0 && h > 0)
        m_page.setViewportSize(QSize(w, h));
}

QVariantMap Phantom::viewportSize() const
{
    QVariantMap result;
    QSize size = m_page.viewportSize();
    result["width"] = size.width();
    result["height"] = size.height();
    return result;
}

#include "phantomjs.moc"

int main(int argc, char** argv)
{
    if (argc < 2) {
        std::cerr << "phantomjs script.js" << std::endl << std::endl;
        return 1;
    }

    QNetworkProxyFactory::setUseSystemConfiguration(true);

    QApplication app(argc, argv);

    app.setWindowIcon(QIcon(":/phantomjs-icon.png"));
    app.setApplicationName("PhantomJS");
    app.setOrganizationName("Ofi Labs");
    app.setOrganizationDomain("www.ofilabs.com");
    app.setApplicationVersion(PHANTOMJS_VERSION_STRING);

    Phantom phantom;
    phantom.execute(QString::fromLocal8Bit(argv[1]));
    app.exec();
    return phantom.returnValue();
}
<|endoftext|>


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

#include "ui/views/examples/tree_view_example.h"

#include "base/utf_string_conversions.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/tree/tree_view.h"
#include "ui/views/controls/tree/tree_view.h"
#include "ui/views/layout/grid_layout.h"

namespace views {
namespace examples {

TreeViewExample::TreeViewExample()
    : ExampleBase("Tree View"),
      model_(new NodeType(ASCIIToUTF16("root"), 1)) {
}

TreeViewExample::~TreeViewExample() {
  // Delete the view before the model.
  delete tree_view_;
  tree_view_ = NULL;
}

void TreeViewExample::CreateExampleView(View* container) {
  // Add some sample data.
  NodeType* colors_node = new NodeType(ASCIIToUTF16("colors"), 1);
  model_.GetRoot()->Add(colors_node, 0);
  colors_node->Add(new NodeType(ASCIIToUTF16("red"), 1), 0);
  colors_node->Add(new NodeType(ASCIIToUTF16("green"), 1), 1);
  colors_node->Add(new NodeType(ASCIIToUTF16("blue"), 1), 2);

  NodeType* sheep_node = new NodeType(ASCIIToUTF16("sheep"), 1);
  model_.GetRoot()->Add(sheep_node, 0);
  sheep_node->Add(new NodeType(ASCIIToUTF16("Sheep 1"), 1), 0);
  sheep_node->Add(new NodeType(ASCIIToUTF16("Sheep 2"), 1), 1);

  tree_view_ = new TreeView();
  tree_view_->set_context_menu_controller(this);
  tree_view_->SetRootShown(false);
  tree_view_->set_lines_at_root(true);
  tree_view_->SetModel(&model_);
  tree_view_->SetController(this);
  add_ = new TextButton(this, ASCIIToUTF16("Add"));
  add_->set_focusable(true);
  remove_ = new TextButton(this, ASCIIToUTF16("Remove"));
  remove_->set_focusable(true);
  change_title_ = new TextButton(this, ASCIIToUTF16("Change Title"));
  change_title_->set_focusable(true);

  GridLayout* layout = new GridLayout(container);
  container->SetLayoutManager(layout);

  const int tree_view_column = 0;
  ColumnSet* column_set = layout->AddColumnSet(tree_view_column);
  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                        1.0f, GridLayout::USE_PREF, 0, 0);
  layout->StartRow(1 /* expand */, tree_view_column);
  layout->AddView(tree_view_->CreateParentIfNecessary());

  // Add control buttons horizontally.
  const int button_column = 1;
  column_set = layout->AddColumnSet(button_column);
  for (int i = 0; i < 3; i++) {
    column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                          1.0f, GridLayout::USE_PREF, 0, 0);
  }

  layout->StartRow(0 /* no expand */, button_column);
  layout->AddView(add_);
  layout->AddView(remove_);
  layout->AddView(change_title_);
}

void TreeViewExample::AddNewNode() {
  NodeType* selected_node =
      static_cast<NodeType*>(tree_view_->GetSelectedNode());
  if (!selected_node)
    selected_node = model_.GetRoot();
  NodeType* new_node = new NodeType(selected_node->GetTitle(), 1);
  model_.Add(selected_node, new_node, selected_node->child_count());
  tree_view_->SetSelectedNode(new_node);
}

bool TreeViewExample::IsCommandIdEnabled(int command_id) {
  return command_id != ID_REMOVE ||
      tree_view_->GetSelectedNode() != model_.GetRoot();
}

void TreeViewExample::ButtonPressed(Button* sender, const Event& event) {
  NodeType* selected_node =
      static_cast<NodeType*>(tree_view_->GetSelectedNode());
  if (sender == add_) {
    AddNewNode();
  } else if (sender == remove_) {
    DCHECK(selected_node);
    DCHECK_NE(model_.GetRoot(), selected_node);
    model_.Remove(selected_node->parent(), selected_node);
  } else if (sender == change_title_) {
    DCHECK(selected_node);
    model_.SetTitle(selected_node,
                    selected_node->GetTitle() + ASCIIToUTF16("new"));
  }
}

void TreeViewExample::OnTreeViewSelectionChanged(TreeView* tree_view) {
  ui::TreeModelNode* node = tree_view_->GetSelectedNode();
  if (node) {
    change_title_->SetEnabled(true);
    remove_->SetEnabled(node != model_.GetRoot());
  } else {
    change_title_->SetEnabled(false);
    remove_->SetEnabled(false);
  }
}

bool TreeViewExample::CanEdit(TreeView* tree_view,
                              ui::TreeModelNode* node) {
  return true;
}

void TreeViewExample::ShowContextMenuForView(View* source,
                                             const gfx::Point& point) {
  ui::SimpleMenuModel context_menu_model(this);
  context_menu_model.AddItem(ID_EDIT, ASCIIToUTF16("Edit"));
  context_menu_model.AddItem(ID_REMOVE, ASCIIToUTF16("Remove"));
  context_menu_model.AddItem(ID_ADD, ASCIIToUTF16("Add"));
  views::MenuModelAdapter menu_adapter(&context_menu_model);
  context_menu_runner_.reset(new views::MenuRunner(menu_adapter.CreateMenu()));
  if (context_menu_runner_->RunMenuAt(source->GetWidget(), NULL,
      gfx::Rect(point, gfx::Size()), views::MenuItemView::TOPLEFT, 0) ==
      views::MenuRunner::MENU_DELETED)
    return;
}

bool TreeViewExample::IsCommandIdChecked(int command_id) const {
  return false;
}

bool TreeViewExample::IsCommandIdEnabled(int command_id) const {
  return const_cast<TreeViewExample*>(this)->IsCommandIdEnabled(command_id);
}

bool TreeViewExample::GetAcceleratorForCommandId(
    int command_id,
    ui::Accelerator* accelerator) {
  return false;
}

void TreeViewExample::ExecuteCommand(int command_id) {
  NodeType* selected_node =
      static_cast<NodeType*>(tree_view_->GetSelectedNode());
  switch (command_id) {
    case ID_EDIT:
      tree_view_->StartEditing(selected_node);
      break;
    case ID_REMOVE:
      model_.Remove(selected_node->parent(), selected_node);
      break;
    case ID_ADD:
      AddNewNode();
      break;
    default:
      NOTREACHED();
  }
}

}  // namespace examples
}  // namespace views
<commit_msg>views/examples: Fix crash when closing views examples window.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/views/examples/tree_view_example.h"

#include "base/utf_string_conversions.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/tree/tree_view.h"
#include "ui/views/controls/tree/tree_view.h"
#include "ui/views/layout/grid_layout.h"

namespace views {
namespace examples {

TreeViewExample::TreeViewExample()
    : ExampleBase("Tree View"),
      tree_view_(NULL),
      model_(new NodeType(ASCIIToUTF16("root"), 1)) {
}

TreeViewExample::~TreeViewExample() {
  // Delete the view before the model.
  delete tree_view_;
  tree_view_ = NULL;
}

void TreeViewExample::CreateExampleView(View* container) {
  // Add some sample data.
  NodeType* colors_node = new NodeType(ASCIIToUTF16("colors"), 1);
  model_.GetRoot()->Add(colors_node, 0);
  colors_node->Add(new NodeType(ASCIIToUTF16("red"), 1), 0);
  colors_node->Add(new NodeType(ASCIIToUTF16("green"), 1), 1);
  colors_node->Add(new NodeType(ASCIIToUTF16("blue"), 1), 2);

  NodeType* sheep_node = new NodeType(ASCIIToUTF16("sheep"), 1);
  model_.GetRoot()->Add(sheep_node, 0);
  sheep_node->Add(new NodeType(ASCIIToUTF16("Sheep 1"), 1), 0);
  sheep_node->Add(new NodeType(ASCIIToUTF16("Sheep 2"), 1), 1);

  tree_view_ = new TreeView();
  tree_view_->set_context_menu_controller(this);
  tree_view_->SetRootShown(false);
  tree_view_->set_lines_at_root(true);
  tree_view_->SetModel(&model_);
  tree_view_->SetController(this);
  add_ = new TextButton(this, ASCIIToUTF16("Add"));
  add_->set_focusable(true);
  remove_ = new TextButton(this, ASCIIToUTF16("Remove"));
  remove_->set_focusable(true);
  change_title_ = new TextButton(this, ASCIIToUTF16("Change Title"));
  change_title_->set_focusable(true);

  GridLayout* layout = new GridLayout(container);
  container->SetLayoutManager(layout);

  const int tree_view_column = 0;
  ColumnSet* column_set = layout->AddColumnSet(tree_view_column);
  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                        1.0f, GridLayout::USE_PREF, 0, 0);
  layout->StartRow(1 /* expand */, tree_view_column);
  layout->AddView(tree_view_->CreateParentIfNecessary());

  // Add control buttons horizontally.
  const int button_column = 1;
  column_set = layout->AddColumnSet(button_column);
  for (int i = 0; i < 3; i++) {
    column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                          1.0f, GridLayout::USE_PREF, 0, 0);
  }

  layout->StartRow(0 /* no expand */, button_column);
  layout->AddView(add_);
  layout->AddView(remove_);
  layout->AddView(change_title_);
}

void TreeViewExample::AddNewNode() {
  NodeType* selected_node =
      static_cast<NodeType*>(tree_view_->GetSelectedNode());
  if (!selected_node)
    selected_node = model_.GetRoot();
  NodeType* new_node = new NodeType(selected_node->GetTitle(), 1);
  model_.Add(selected_node, new_node, selected_node->child_count());
  tree_view_->SetSelectedNode(new_node);
}

bool TreeViewExample::IsCommandIdEnabled(int command_id) {
  return command_id != ID_REMOVE ||
      tree_view_->GetSelectedNode() != model_.GetRoot();
}

void TreeViewExample::ButtonPressed(Button* sender, const Event& event) {
  NodeType* selected_node =
      static_cast<NodeType*>(tree_view_->GetSelectedNode());
  if (sender == add_) {
    AddNewNode();
  } else if (sender == remove_) {
    DCHECK(selected_node);
    DCHECK_NE(model_.GetRoot(), selected_node);
    model_.Remove(selected_node->parent(), selected_node);
  } else if (sender == change_title_) {
    DCHECK(selected_node);
    model_.SetTitle(selected_node,
                    selected_node->GetTitle() + ASCIIToUTF16("new"));
  }
}

void TreeViewExample::OnTreeViewSelectionChanged(TreeView* tree_view) {
  ui::TreeModelNode* node = tree_view_->GetSelectedNode();
  if (node) {
    change_title_->SetEnabled(true);
    remove_->SetEnabled(node != model_.GetRoot());
  } else {
    change_title_->SetEnabled(false);
    remove_->SetEnabled(false);
  }
}

bool TreeViewExample::CanEdit(TreeView* tree_view,
                              ui::TreeModelNode* node) {
  return true;
}

void TreeViewExample::ShowContextMenuForView(View* source,
                                             const gfx::Point& point) {
  ui::SimpleMenuModel context_menu_model(this);
  context_menu_model.AddItem(ID_EDIT, ASCIIToUTF16("Edit"));
  context_menu_model.AddItem(ID_REMOVE, ASCIIToUTF16("Remove"));
  context_menu_model.AddItem(ID_ADD, ASCIIToUTF16("Add"));
  views::MenuModelAdapter menu_adapter(&context_menu_model);
  context_menu_runner_.reset(new views::MenuRunner(menu_adapter.CreateMenu()));
  if (context_menu_runner_->RunMenuAt(source->GetWidget(), NULL,
      gfx::Rect(point, gfx::Size()), views::MenuItemView::TOPLEFT, 0) ==
      views::MenuRunner::MENU_DELETED)
    return;
}

bool TreeViewExample::IsCommandIdChecked(int command_id) const {
  return false;
}

bool TreeViewExample::IsCommandIdEnabled(int command_id) const {
  return const_cast<TreeViewExample*>(this)->IsCommandIdEnabled(command_id);
}

bool TreeViewExample::GetAcceleratorForCommandId(
    int command_id,
    ui::Accelerator* accelerator) {
  return false;
}

void TreeViewExample::ExecuteCommand(int command_id) {
  NodeType* selected_node =
      static_cast<NodeType*>(tree_view_->GetSelectedNode());
  switch (command_id) {
    case ID_EDIT:
      tree_view_->StartEditing(selected_node);
      break;
    case ID_REMOVE:
      model_.Remove(selected_node->parent(), selected_node);
      break;
    case ID_ADD:
      AddNewNode();
      break;
    default:
      NOTREACHED();
  }
}

}  // namespace examples
}  // namespace views
<|endoftext|>


<commit_before><commit_msg>修正解析obj纹理坐标的一个BUG<commit_after><|endoftext|>