<commit_before>/******************************************************************************
  This source file is part of the Avogadro project.
  This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#include "label.h"

#include <avogadro/core/elements.h>
#include <avogadro/core/molecule.h>
#include <avogadro/core/residue.h>
#include <avogadro/qtgui/colorbutton.h>
#include <avogadro/rendering/geometrynode.h>
#include <avogadro/rendering/scene.h>
#include <avogadro/rendering/textlabel3d.h>

#include <QtCore/QSettings>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

namespace Avogadro {
namespace QtPlugins {

using Avogadro::Rendering::TextLabel3D;
using Core::Array;
using Core::Atom;
using Core::Elements;
using Core::Molecule;
using QtGui::PluginLayerManager;
using Rendering::GeometryNode;
using Rendering::GroupNode;
using std::map;

typedef Array<Molecule::BondType> NeighborListType;

namespace {
TextLabel3D* createLabel(const std::string& text, const Vector3f& pos,
                         float radius, const Vector3ub& color)
{
  Rendering::TextProperties tprop;
  tprop.setAlign(Rendering::TextProperties::HCenter,
                 Rendering::TextProperties::VCenter);
  tprop.setFontFamily(Rendering::TextProperties::SansSerif);
  tprop.setColorRgb(color.data());

  TextLabel3D* label = new TextLabel3D;
  label->setText(text);
  label->setRenderPass(Rendering::TranslucentPass);
  label->setTextProperties(tprop);
  label->setRadius(radius);
  label->setAnchor(pos);
  return label;
}
} // namespace

struct LayerLabel : Core::LayerData
{
  enum LabelOptions : char
  {
    None = 0x00,
    Index = 0x01,
    Name = 0x02,
    Custom = 0x04,
    Ordinal = 0x08
  };
  char atomOptions;
  char residueOptions;

  QWidget* widget;
  float radiusScalar;
  Vector3ub color;

  LayerLabel()
  {
    widget = nullptr;
    QSettings settings;
    atomOptions = char(settings.value("label/atomoptions", 0x02).toInt());
    residueOptions = char(settings.value("label/residueoptions", 0x00).toInt());
    radiusScalar = settings.value("label/radiusscalar", 0.5).toDouble();

    QColor q_color =
      settings.value("label/color", QColor(Qt::white)).value<QColor>();
    color[0] = static_cast<unsigned char>(q_color.red());
    color[1] = static_cast<unsigned char>(q_color.green());
    color[2] = static_cast<unsigned char>(q_color.blue());
  }

  ~LayerLabel()
  {
    if (widget)
      widget->deleteLater();
  }

  std::string serialize() override final
  {
    std::string aux = (const char*)atomOptions;
    std::string aux2 = (const char*)residueOptions;
    return aux + " " + aux2 + " " + std::to_string(radiusScalar) + " " +
           std::to_string(color[0]) + " " + std::to_string(color[1]) + " " +
           std::to_string(color[2]);
  }
  void deserialize(std::string text) override final
  {
    std::stringstream ss(text);
    std::string aux;
    ss >> aux;
    atomOptions = aux[0];
    ss >> aux;
    residueOptions = aux[0];
    ss >> aux;
    radiusScalar = std::stof(aux);
    ss >> aux;
    color[0] = std::stoi(aux);
    ss >> aux;
    color[1] = std::stoi(aux);
    ss >> aux;
    color[2] = std::stoi(aux);
  }

  void setupWidget(Label* slot)
  {
    if (!widget) {
      widget = new QWidget(qobject_cast<QWidget*>(slot->parent()));
      QVBoxLayout* v = new QVBoxLayout;

      QFormLayout* form = new QFormLayout;
      // color button
      QtGui::ColorButton* color = new QtGui::ColorButton;
      QObject::connect(color, SIGNAL(colorChanged(const QColor&)), slot,
                       SLOT(setColor(const QColor&)));
      form->addRow(QObject::tr("Color:"), color);

      // radius scalar
      QDoubleSpinBox* spin = new QDoubleSpinBox;
      spin->setRange(0.0, 1.5);
      spin->setSingleStep(0.1);
      spin->setDecimals(1);
      spin->setValue(radiusScalar);
      QObject::connect(spin, SIGNAL(valueChanged(double)), slot,
                       SLOT(setRadiusScalar(double)));
      form->addRow(QObject::tr("Distance from center:"), spin);

      QComboBox* atom = new QComboBox;
      atom->setObjectName("atom");
      for (char i = 0x00; i < std::pow(2, 4); ++i) {
        if (i == 0) {
          atom->addItem(QObject::tr("None"), QVariant(LabelOptions::None));
        } else {
          char val = 0x00;
          QStringList text;
          if (i & LabelOptions::Custom) {
            text << QObject::tr("Custom");
            val = LabelOptions::Custom;
          }
          if (i & LabelOptions::Index) {
            text << ((text.size() == 0) ? QObject::tr("Index")
                                        : QObject::tr("In."));
            val |= LabelOptions::Index;
          }
          if (i & LabelOptions::Name) {
            text << ((text.size() == 0) ? QObject::tr("Element")
                                        : QObject::tr("El."));
            val |= LabelOptions::Name;
          }
          if (i & LabelOptions::Ordinal) {
            text << ((text.size() == 0) ? QObject::tr("Element & Ordinal")
                                        : QObject::tr("El.&Or."));
            val |= LabelOptions::Ordinal;
          }
          QString join = QObject::tr(", ");
          atom->addItem(text.join(join), QVariant(val));
          if (val == atomOptions) {
            atom->setCurrentText(text.join(join));
          }
        }
      }
      QObject::connect(atom, SIGNAL(currentIndexChanged(int)), slot,
                       SLOT(atomLabelType(int)));
      int index = atom->findData(int(atomOptions));
      atom->model()->sort(0, Qt::AscendingOrder);
      form->addRow(QObject::tr("Atom Label:"), atom);

      QComboBox* residue = new QComboBox;
      residue->setObjectName("residue");
      for (char i = 0x00; i < std::pow(2, 2); ++i) {
        if (i == 0) {
          residue->addItem(QObject::tr("None"), QVariant(LabelOptions::None));
        } else {
          char val = 0x00;
          QStringList text;
          if (i & LabelOptions::Index) {
            text << QObject::tr("ID");
            val |= LabelOptions::Index;
          }
          if (i & LabelOptions::Name) {
            text << QObject::tr("Name");
            val |= LabelOptions::Name;
          }
          if (val != 0x00) {
            QString join = QObject::tr(" & ");
            residue->addItem(text.join(join), QVariant(val));
            if (val == residueOptions) {
              residue->setCurrentText(text.join(join));
            }
          }
        }
      }
      QObject::connect(residue, SIGNAL(currentIndexChanged(int)), slot,
                       SLOT(residueLabelType(int)));
      index = residue->findData(int(residueOptions));
      residue->model()->sort(0, Qt::AscendingOrder);
      form->addRow(QObject::tr("Residue Label:"), residue);

      v->addLayout(form);
      v->addStretch(1);
      widget->setLayout(v);
    }
  }
};

Label::Label(QObject* parent_) : QtGui::ScenePlugin(parent_)
{
  m_layerManager = PluginLayerManager(m_name);
}

Label::~Label() {}

void Label::process(const Core::Molecule& molecule, Rendering::GroupNode& node)
{
  m_layerManager.load<LayerLabel>();
  for (size_t layer = 0; layer < m_layerManager.layerCount(); ++layer) {
    LayerLabel& interface = m_layerManager.getSetting<LayerLabel>(layer);
    if (interface.residueOptions) {
      processResidue(molecule, node, layer);
    }
    if (interface.atomOptions) {
      processAtom(molecule, node, layer);
    }
  }
}

void Label::processResidue(const Core::Molecule& molecule,
                           Rendering::GroupNode& node, size_t layer)
{
  GeometryNode* geometry = new GeometryNode;
  node.addChild(geometry);

  for (const auto& residue : molecule.residues()) {
    Atom caAtom = residue.getAtomByName("CA");
    if (!caAtom.isValid() ||
        !m_layerManager.atomEnabled(layer, caAtom.index())) {
      continue;
    }
    auto name = residue.residueName();
    const auto atoms = residue.residueAtoms();
    Vector3f pos = Vector3f::Zero();
    for (const auto& atom : atoms) {
      pos += atom.position3d().cast<float>();
    }
    pos /= static_cast<float>(atoms.size());

    float radius = 0.0f;
    for (const auto& atom : atoms) {
      unsigned char atomicNumber = atom.atomicNumber();
      float auxR = static_cast<float>(Elements::radiusVDW(atomicNumber));
      auxR += (atom.position3d().cast<float>() - pos).norm();
      if (auxR > radius) {
        auxR = radius;
      }
    }

    auto& interface = m_layerManager.getSetting<LayerLabel>(layer);
    Vector3ub color = interface.color;
    std::string text = "";
    if (interface.residueOptions & LayerLabel::LabelOptions::Index) {
      text = std::to_string(residue.residueId());
    }
    if (interface.residueOptions & LayerLabel::LabelOptions::Name) {
      text += (text == "" ? "" : " / ") + name;
    }
    TextLabel3D* residueLabel = createLabel(text, pos, radius, color);
    geometry->addDrawable(residueLabel);
  }
}

void Label::processAtom(const Core::Molecule& molecule,
                        Rendering::GroupNode& node, size_t layer)
{
  GeometryNode* geometry = new GeometryNode;
  node.addChild(geometry);

  std::map<unsigned char, size_t> atomCount;
  for (Index i = 0; i < molecule.atomCount(); ++i) {
    Core::Atom atom = molecule.atom(i);

    unsigned char atomicNumber = atom.atomicNumber();
    if (atomCount.find(atomicNumber) == atomCount.end()) {
      atomCount[atomicNumber] = 1;
    } else {
      ++atomCount[atomicNumber];
    }

    if (!m_layerManager.atomEnabled(layer, i)) {
      continue;
    }

    LayerLabel& interface = m_layerManager.getSetting<LayerLabel>(layer);
    std::string text = "";
    if (interface.atomOptions & LayerLabel::LabelOptions::Custom) {
      text += (text == "" ? "" : " / ") + atom.label();
    }
    if (interface.atomOptions & LayerLabel::LabelOptions::Index) {
      text += (text == "" ? "" : " / ") + std::to_string(atom.index());
    }
    if (interface.atomOptions & LayerLabel::LabelOptions::Name) {
      text +=
        (text == "" ? "" : " / ") + std::string(Elements::symbol(atomicNumber));
    }
    if (interface.atomOptions & LayerLabel::LabelOptions::Ordinal) {
      text += (text == "" ? "" : " / ") +
              std::string(Elements::symbol(atomicNumber) +
                          std::to_string(atomCount[atomicNumber]));
    }
    if (text != "") {
      const Vector3f pos(atom.position3d().cast<float>());
      Vector3ub color = interface.color;
      float radius = static_cast<float>(Elements::radiusVDW(atomicNumber)) *
                     interface.radiusScalar;

      TextLabel3D* atomLabel = createLabel(text, pos, radius, color);
      geometry->addDrawable(atomLabel);
    }
  }
}

void Label::setColor(const QColor& color)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();

  interface.color[0] = static_cast<unsigned char>(color.red());
  interface.color[1] = static_cast<unsigned char>(color.green());
  interface.color[2] = static_cast<unsigned char>(color.blue());

  emit drawablesChanged();

  QSettings settings;
  settings.setValue("label/color", color);
}

void Label::atomLabelType(int index)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.atomOptions = char(setupWidget()
                                 ->findChildren<QComboBox*>("atom")[0]
                                 ->itemData(index)
                                 .toInt());
  emit drawablesChanged();
}

void Label::residueLabelType(int index)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.residueOptions = char(setupWidget()
                                    ->findChildren<QComboBox*>("residue")[0]
                                    ->itemData(index)
                                    .toInt());
  emit drawablesChanged();
}

void Label::setRadiusScalar(double radius)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.radiusScalar = float(radius);
  emit drawablesChanged();

  QSettings settings;
  settings.setValue("label/radiusScalar", interface.radiusScalar);
}

QWidget* Label::setupWidget()
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.setupWidget(this);
  return interface.widget;
}

} // namespace QtPlugins
} // namespace Avogadro
<commit_msg>remove extra label options<commit_after>/******************************************************************************
  This source file is part of the Avogadro project.
  This source code is released under the 3-Clause BSD License, (see "LICENSE").
******************************************************************************/

#include "label.h"

#include <avogadro/core/elements.h>
#include <avogadro/core/molecule.h>
#include <avogadro/core/residue.h>
#include <avogadro/qtgui/colorbutton.h>
#include <avogadro/rendering/geometrynode.h>
#include <avogadro/rendering/scene.h>
#include <avogadro/rendering/textlabel3d.h>

#include <QtCore/QSettings>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QComboBox>
#include <QtWidgets/QDoubleSpinBox>
#include <QtWidgets/QFormLayout>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>

namespace Avogadro {
namespace QtPlugins {

using Avogadro::Rendering::TextLabel3D;
using Core::Array;
using Core::Atom;
using Core::Elements;
using Core::Molecule;
using QtGui::PluginLayerManager;
using Rendering::GeometryNode;
using Rendering::GroupNode;
using std::map;

typedef Array<Molecule::BondType> NeighborListType;

namespace {
TextLabel3D* createLabel(const std::string& text, const Vector3f& pos,
                         float radius, const Vector3ub& color)
{
  Rendering::TextProperties tprop;
  tprop.setAlign(Rendering::TextProperties::HCenter,
                 Rendering::TextProperties::VCenter);
  tprop.setFontFamily(Rendering::TextProperties::SansSerif);
  tprop.setColorRgb(color.data());

  TextLabel3D* label = new TextLabel3D;
  label->setText(text);
  label->setRenderPass(Rendering::TranslucentPass);
  label->setTextProperties(tprop);
  label->setRadius(radius);
  label->setAnchor(pos);
  return label;
}
} // namespace

struct LayerLabel : Core::LayerData
{
  enum LabelOptions : char
  {
    None = 0x00,
    Index = 0x01,
    Name = 0x02,
    Custom = 0x04,
    Ordinal = 0x08
  };
  char atomOptions;
  char residueOptions;

  QWidget* widget;
  float radiusScalar;
  Vector3ub color;

  LayerLabel()
  {
    widget = nullptr;
    QSettings settings;
    atomOptions = char(settings.value("label/atomoptions", 0x02).toInt());
    residueOptions = char(settings.value("label/residueoptions", 0x00).toInt());
    radiusScalar = settings.value("label/radiusscalar", 0.5).toDouble();

    QColor q_color =
      settings.value("label/color", QColor(Qt::white)).value<QColor>();
    color[0] = static_cast<unsigned char>(q_color.red());
    color[1] = static_cast<unsigned char>(q_color.green());
    color[2] = static_cast<unsigned char>(q_color.blue());
  }

  ~LayerLabel()
  {
    if (widget)
      widget->deleteLater();
  }

  std::string serialize() override final
  {
    std::string aux = (const char*)atomOptions;
    std::string aux2 = (const char*)residueOptions;
    return aux + " " + aux2 + " " + std::to_string(radiusScalar) + " " +
           std::to_string(color[0]) + " " + std::to_string(color[1]) + " " +
           std::to_string(color[2]);
  }
  void deserialize(std::string text) override final
  {
    std::stringstream ss(text);
    std::string aux;
    ss >> aux;
    atomOptions = aux[0];
    ss >> aux;
    residueOptions = aux[0];
    ss >> aux;
    radiusScalar = std::stof(aux);
    ss >> aux;
    color[0] = std::stoi(aux);
    ss >> aux;
    color[1] = std::stoi(aux);
    ss >> aux;
    color[2] = std::stoi(aux);
  }

  void setupWidget(Label* slot)
  {
    if (!widget) {
      widget = new QWidget(qobject_cast<QWidget*>(slot->parent()));
      QVBoxLayout* v = new QVBoxLayout;

      QFormLayout* form = new QFormLayout;
      // color button
      QtGui::ColorButton* colorButton = new QtGui::ColorButton;
      QObject::connect(colorButton, SIGNAL(colorChanged(const QColor&)), slot,
                       SLOT(setColor(const QColor&)));
      form->addRow(QObject::tr("Color:"), colorButton);

      // radius scalar
      QDoubleSpinBox* spin = new QDoubleSpinBox;
      spin->setRange(0.0, 1.5);
      spin->setSingleStep(0.1);
      spin->setDecimals(1);
      spin->setValue(radiusScalar);
      QObject::connect(spin, SIGNAL(valueChanged(double)), slot,
                       SLOT(setRadiusScalar(double)));
      form->addRow(QObject::tr("Distance from center:"), spin);

      QComboBox* atom = new QComboBox;
      atom->setObjectName("atom");
      char elements[] = { None, Index, Name, Custom, Ordinal };
      for (unsigned char i = 0; i < 5; ++i) {
        char option = elements[i];
        if (option == 0) {
          atom->addItem(QObject::tr("None"), QVariant(LabelOptions::None));
        } else {
          char val = LabelOptions::None;
          QStringList text;
          if (option & LabelOptions::Custom) {
            text << QObject::tr("Custom");
            val = LabelOptions::Custom;
          }
          if (option & LabelOptions::Index) {
            text << ((text.size() == 0) ? QObject::tr("Index")
                                        : QObject::tr("In."));
            val |= LabelOptions::Index;
          }
          if (option & LabelOptions::Name) {
            text << ((text.size() == 0) ? QObject::tr("Element")
                                        : QObject::tr("El."));
            val |= LabelOptions::Name;
          }
          if (option & LabelOptions::Ordinal) {
            text << ((text.size() == 0) ? QObject::tr("Element & Ordinal")
                                        : QObject::tr("El.&Or."));
            val |= LabelOptions::Ordinal;
          }
          QString join = QObject::tr(", ");
          atom->addItem(text.join(join), QVariant(val));
          if (val == atomOptions) {
            atom->setCurrentText(text.join(join));
          }
        }
      }
      QObject::connect(atom, SIGNAL(currentIndexChanged(int)), slot,
                       SLOT(atomLabelType(int)));
      int index = atom->findData(int(atomOptions));
      atom->model()->sort(0, Qt::AscendingOrder);
      form->addRow(QObject::tr("Atom Label:"), atom);

      QComboBox* residue = new QComboBox;
      residue->setObjectName("residue");
      for (char i = 0x00; i < std::pow(2, 2); ++i) {
        if (i == 0) {
          residue->addItem(QObject::tr("None"), QVariant(LabelOptions::None));
        } else {
          char val = 0x00;
          QStringList text;
          if (i & LabelOptions::Index) {
            text << QObject::tr("ID");
            val |= LabelOptions::Index;
          }
          if (i & LabelOptions::Name) {
            text << QObject::tr("Name");
            val |= LabelOptions::Name;
          }
          if (val != 0x00) {
            QString join = QObject::tr(" & ");
            residue->addItem(text.join(join), QVariant(val));
            if (val == residueOptions) {
              residue->setCurrentText(text.join(join));
            }
          }
        }
      }
      QObject::connect(residue, SIGNAL(currentIndexChanged(int)), slot,
                       SLOT(residueLabelType(int)));
      index = residue->findData(int(residueOptions));
      residue->model()->sort(0, Qt::AscendingOrder);
      form->addRow(QObject::tr("Residue Label:"), residue);

      v->addLayout(form);
      v->addStretch(1);
      widget->setLayout(v);
    }
  }
};

Label::Label(QObject* parent_) : QtGui::ScenePlugin(parent_)
{
  m_layerManager = PluginLayerManager(m_name);
}

Label::~Label() {}

void Label::process(const Core::Molecule& molecule, Rendering::GroupNode& node)
{
  m_layerManager.load<LayerLabel>();
  for (size_t layer = 0; layer < m_layerManager.layerCount(); ++layer) {
    LayerLabel& interface = m_layerManager.getSetting<LayerLabel>(layer);
    if (interface.residueOptions) {
      processResidue(molecule, node, layer);
    }
    if (interface.atomOptions) {
      processAtom(molecule, node, layer);
    }
  }
}

void Label::processResidue(const Core::Molecule& molecule,
                           Rendering::GroupNode& node, size_t layer)
{
  GeometryNode* geometry = new GeometryNode;
  node.addChild(geometry);

  for (const auto& residue : molecule.residues()) {
    Atom caAtom = residue.getAtomByName("CA");
    if (!caAtom.isValid() ||
        !m_layerManager.atomEnabled(layer, caAtom.index())) {
      continue;
    }
    auto name = residue.residueName();
    const auto atoms = residue.residueAtoms();
    Vector3f pos = Vector3f::Zero();
    for (const auto& atom : atoms) {
      pos += atom.position3d().cast<float>();
    }
    pos /= static_cast<float>(atoms.size());

    float radius = 0.0f;
    for (const auto& atom : atoms) {
      unsigned char atomicNumber = atom.atomicNumber();
      float auxR = static_cast<float>(Elements::radiusVDW(atomicNumber));
      auxR += (atom.position3d().cast<float>() - pos).norm();
      if (auxR > radius) {
        auxR = radius;
      }
    }

    auto& interface = m_layerManager.getSetting<LayerLabel>(layer);
    Vector3ub color = interface.color;
    std::string text = "";
    if (interface.residueOptions & LayerLabel::LabelOptions::Index) {
      text = std::to_string(residue.residueId());
    }
    if (interface.residueOptions & LayerLabel::LabelOptions::Name) {
      text += (text == "" ? "" : " / ") + name;
    }
    TextLabel3D* residueLabel = createLabel(text, pos, radius, color);
    geometry->addDrawable(residueLabel);
  }
}

void Label::processAtom(const Core::Molecule& molecule,
                        Rendering::GroupNode& node, size_t layer)
{
  GeometryNode* geometry = new GeometryNode;
  node.addChild(geometry);

  std::map<unsigned char, size_t> atomCount;
  for (Index i = 0; i < molecule.atomCount(); ++i) {
    Core::Atom atom = molecule.atom(i);

    unsigned char atomicNumber = atom.atomicNumber();
    if (atomCount.find(atomicNumber) == atomCount.end()) {
      atomCount[atomicNumber] = 1;
    } else {
      ++atomCount[atomicNumber];
    }

    if (!m_layerManager.atomEnabled(layer, i)) {
      continue;
    }

    LayerLabel& interface = m_layerManager.getSetting<LayerLabel>(layer);
    std::string text = "";
    if (interface.atomOptions & LayerLabel::LabelOptions::Custom) {
      text += (text == "" ? "" : " / ") + atom.label();
    }
    if (interface.atomOptions & LayerLabel::LabelOptions::Index) {
      text += (text == "" ? "" : " / ") + std::to_string(atom.index());
    }
    if (interface.atomOptions & LayerLabel::LabelOptions::Name) {
      text +=
        (text == "" ? "" : " / ") + std::string(Elements::symbol(atomicNumber));
    }
    if (interface.atomOptions & LayerLabel::LabelOptions::Ordinal) {
      text += (text == "" ? "" : " / ") +
              std::string(Elements::symbol(atomicNumber) +
                          std::to_string(atomCount[atomicNumber]));
    }
    if (text != "") {
      const Vector3f pos(atom.position3d().cast<float>());
      Vector3ub color = interface.color;
      float radius = static_cast<float>(Elements::radiusVDW(atomicNumber)) *
                     interface.radiusScalar;

      TextLabel3D* atomLabel = createLabel(text, pos, radius, color);
      geometry->addDrawable(atomLabel);
    }
  }
}

void Label::setColor(const QColor& color)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();

  interface.color[0] = static_cast<unsigned char>(color.red());
  interface.color[1] = static_cast<unsigned char>(color.green());
  interface.color[2] = static_cast<unsigned char>(color.blue());

  emit drawablesChanged();

  QSettings settings;
  settings.setValue("label/color", color);
}

void Label::atomLabelType(int index)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.atomOptions = char(setupWidget()
                                 ->findChildren<QComboBox*>("atom")[0]
                                 ->itemData(index)
                                 .toInt());
  emit drawablesChanged();
}

void Label::residueLabelType(int index)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.residueOptions = char(setupWidget()
                                    ->findChildren<QComboBox*>("residue")[0]
                                    ->itemData(index)
                                    .toInt());
  emit drawablesChanged();
}

void Label::setRadiusScalar(double radius)
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.radiusScalar = float(radius);
  emit drawablesChanged();

  QSettings settings;
  settings.setValue("label/radiusScalar", interface.radiusScalar);
}

QWidget* Label::setupWidget()
{
  LayerLabel& interface = m_layerManager.getSetting<LayerLabel>();
  interface.setupWidget(this);
  return interface.widget;
}

} // namespace QtPlugins
} // namespace Avogadro
<|endoftext|>


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

#include "ref_counted.hpp"
#include "dlib/threads.h"
#include <libkern/OSAtomic.h>

static dlib::rmutex sRefMutex;

RefCounted::~RefCounted()
{
}

void RefCounted::referTo()
{
#ifdef _WINDOWS
  InterlockedIncrement(&this->mRefCount);
#else
#ifdef MACOSX
  OSAtomicIncrement32Barrier(&(this->mRefCount));
#else
  dlib::auto_mutex lock(sRefMutex);
  mRefCount++;
#endif
#endif
}

void RefCounted::unrefer()
{
#ifdef _WINDOWS
  if (InterlockedDecrement(&this->mRefCount) <= 0)
  {
    delete this;
  }
#else
#ifdef MACOSX
  if (OSAtomicDecrement32Barrier(&(this->mRefCount)) <= 0)
  {
    delete this;
  }
#else
  dlib::auto_mutex lock(sRefMutex);
  if (--mRefCount <= 0)
  {
    delete this;
  }
#endif
#endif
}

<commit_msg>Made windows interlocked increment cleaner like *nix version.<commit_after>/*
 * Copyright Copyright 2012, System Insights, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include "ref_counted.hpp"
#include "dlib/threads.h"
#include <libkern/OSAtomic.h>

static dlib::rmutex sRefMutex;

RefCounted::~RefCounted()
{
}

void RefCounted::referTo()
{
#ifdef _WINDOWS
  InterlockedIncrement(&(this->mRefCount));
#else
#ifdef MACOSX
  OSAtomicIncrement32Barrier(&(this->mRefCount));
#else
  dlib::auto_mutex lock(sRefMutex);
  mRefCount++;
#endif
#endif
}

void RefCounted::unrefer()
{
#ifdef _WINDOWS
  if (InterlockedDecrement(&(this->mRefCount)) <= 0)
  {
    delete this;
  }
#else
#ifdef MACOSX
  if (OSAtomicDecrement32Barrier(&(this->mRefCount)) <= 0)
  {
    delete this;
  }
#else
  dlib::auto_mutex lock(sRefMutex);
  if (--mRefCount <= 0)
  {
    delete this;
  }
#endif
#endif
}

<|endoftext|>


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

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _IMPLHELPER_HXX_
#include "ImplHelper.hxx"
#endif

#ifndef _RTL_TENCINFO_H
#include <rtl/tencinfo.h>
#endif

#ifndef _RTL_MEMORY_H_
#include <rtl/memory.h>
#endif

#include <memory>
#if defined _MSC_VER
#pragma warning(push,1)
#endif
#include <windows.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

//------------------------------------------------------------------------
// defines
//------------------------------------------------------------------------

#define FORMATETC_EXACT_MATCH    1
#define FORMATETC_PARTIAL_MATCH -1
#define FORMATETC_NO_MATCH       0

//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------

using ::rtl::OUString;
using ::rtl::OString;

//------------------------------------------------------------------------
// returns a windows codepage appropriate to the
// given mime charset parameter value
//------------------------------------------------------------------------

sal_uInt32 SAL_CALL getWinCPFromMimeCharset( const OUString& charset )
{
    sal_uInt32 winCP = GetACP( );

    if ( charset.getLength( ) )
    {
        OString osCharset(
            charset.getStr( ), charset.getLength( ), RTL_TEXTENCODING_ASCII_US );

        rtl_TextEncoding txtEnc =
            rtl_getTextEncodingFromMimeCharset( osCharset.getStr( ) );

        sal_uInt32 winChrs = rtl_getBestWindowsCharsetFromTextEncoding( txtEnc );

        CHARSETINFO chrsInf;
        sal_Bool bRet = TranslateCharsetInfo( (DWORD*)winChrs, &chrsInf, TCI_SRCCHARSET ) ?
                        sal_True : sal_False;

        // if one of the above functions fails
        // we will return the current ANSI codepage
        // of this thread
        if ( bRet )
            winCP = chrsInf.ciACP;
    }

    return winCP;
}

//--------------------------------------------------
// returns a windows codepage appropriate to the
// given locale and locale type
//--------------------------------------------------

OUString SAL_CALL getWinCPFromLocaleId( LCID lcid, LCTYPE lctype )
{
    OSL_ASSERT( IsValidLocale( lcid, LCID_SUPPORTED ) );

    // we set an default value
    OUString winCP;

    // set an default value
    sal_Unicode wcstr[10];

    if ( LOCALE_IDEFAULTCODEPAGE == lctype )
    {
        _itow( GetOEMCP( ), wcstr, 10 );
        winCP = OUString( wcstr, wcslen( wcstr ) );
    }
    else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype )
    {
        _itow( GetACP( ), wcstr, 10 );
        winCP = OUString( wcstr, wcslen( wcstr ) );
    }
    else
        OSL_ASSERT( sal_False );

    // we use the GetLocaleInfoA because don't want to provide
    // a unicode wrapper function for Win9x in sal/systools
    char buff[6];
    sal_Int32 nResult = GetLocaleInfoA(
        lcid, lctype | LOCALE_USE_CP_ACP, buff, sizeof( buff ) );

    OSL_ASSERT( nResult );

    if ( nResult )
    {
        sal_Int32 len = MultiByteToWideChar(
            CP_ACP, 0, buff, -1, NULL, 0 );

        OSL_ASSERT( len > 0 );

        std::auto_ptr< sal_Unicode > lpwchBuff( new sal_Unicode[len] );

        if ( NULL != lpwchBuff.get( ) )
        {
            len = MultiByteToWideChar(
                CP_ACP, 0, buff, -1, lpwchBuff.get( ), len );

            winCP = OUString( lpwchBuff.get( ), (len - 1) );
        }
    }

    return winCP;
}

//--------------------------------------------------
// returns a mime charset parameter value appropriate
// to the given codepage, optional a prefix can be
// given, e.g. "windows-" or "cp"
//--------------------------------------------------

OUString SAL_CALL getMimeCharsetFromWinCP( sal_uInt32 cp, const OUString& aPrefix )
{
    return aPrefix + cptostr( cp );
}

//--------------------------------------------------
// returns a mime charset parameter value appropriate
// to the given locale id and locale type, optional a
// prefix can be given, e.g. "windows-" or "cp"
//--------------------------------------------------

OUString SAL_CALL getMimeCharsetFromLocaleId( LCID lcid, LCTYPE lctype, const OUString& aPrefix  )
{
    OUString charset = getWinCPFromLocaleId( lcid, lctype );
    return aPrefix + charset;
}

//------------------------------------------------------------------------
// IsOEMCP
//------------------------------------------------------------------------

sal_Bool SAL_CALL IsOEMCP( sal_uInt32 codepage )
{
    OSL_ASSERT( IsValidCodePage( codepage ) );

    sal_uInt32 arrOEMCP[] = { 437, 708, 709, 710, 720, 737,
                              775, 850, 852, 855, 857, 860,
                              861, 862, 863, 864, 865, 866,
                              869, 874, 932, 936, 949, 950, 1361 };

    for ( sal_Int8 i = 0; i < ( sizeof( arrOEMCP )/sizeof( sal_uInt32 ) ); ++i )
        if ( arrOEMCP[i] == codepage )
            return sal_True;

    return sal_False;
}

//------------------------------------------------------------------------
// converts a codepage into its string representation
//------------------------------------------------------------------------

OUString SAL_CALL cptostr( sal_uInt32 codepage )
{
    OSL_ASSERT( IsValidCodePage( codepage ) );

    sal_Unicode cpStr[6];
    _itow( codepage, cpStr, 10 );
    return OUString( cpStr, wcslen( cpStr ) );
}

//-------------------------------------------------------------------------
// OleStdDeleteTargetDevice()
//
// Purpose:
//
// Parameters:
//
// Return Value:
//    SCODE  -  S_OK if successful
//-------------------------------------------------------------------------

void SAL_CALL DeleteTargetDevice( DVTARGETDEVICE* ptd )
{
    __try
    {
        CoTaskMemFree( ptd );
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error DeleteTargetDevice" );
    }
}

//-------------------------------------------------------------------------
// OleStdCopyTargetDevice()
//
// Purpose:
//  duplicate a TARGETDEVICE struct. this function allocates memory for
//  the copy. the caller MUST free the allocated copy when done with it
//  using the standard allocator returned from CoGetMalloc.
//  (OleStdFree can be used to free the copy).
//
// Parameters:
//  ptdSrc      pointer to source TARGETDEVICE
//
// Return Value:
//    pointer to allocated copy of ptdSrc
//    if ptdSrc==NULL then retuns NULL is returned.
//    if ptdSrc!=NULL and memory allocation fails, then NULL is returned
//-------------------------------------------------------------------------

DVTARGETDEVICE* SAL_CALL CopyTargetDevice( DVTARGETDEVICE* ptdSrc )
{
    DVTARGETDEVICE* ptdDest = NULL;

    __try
    {
        if ( NULL != ptdSrc )
        {
            ptdDest = static_cast< DVTARGETDEVICE* >( CoTaskMemAlloc( ptdSrc->tdSize ) );
            rtl_copyMemory( ptdDest, ptdSrc, static_cast< size_t >( ptdSrc->tdSize ) );
        }
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
    }

    return ptdDest;
}

//-------------------------------------------------------------------------
// OleStdCopyFormatEtc()
//
// Purpose:
//  Copies the contents of a FORMATETC structure. this function takes
//  special care to copy correctly copying the pointer to the TARGETDEVICE
//  contained within the source FORMATETC structure.
//  if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy
//  of the TARGETDEVICE will be allocated for the destination of the
//  FORMATETC (petcDest).
//
//  NOTE: the caller MUST free the allocated copy of the TARGETDEVICE
//  within the destination FORMATETC when done with it
//  using the standard allocator returned from CoGetMalloc.
//  (OleStdFree can be used to free the copy).
//
// Parameters:
//  petcDest      pointer to destination FORMATETC
//  petcSrc       pointer to source FORMATETC
//
// Return Value:
//  returns TRUE if copy was successful;
//  retuns FALSE if not successful, e.g. one or both of the pointers
//  were invalid or the pointers were equal
//-------------------------------------------------------------------------

sal_Bool SAL_CALL CopyFormatEtc( LPFORMATETC petcDest, LPFORMATETC petcSrc )
{
    sal_Bool bRet = sal_False;

    __try
    {
        if ( petcDest == petcSrc )
            __leave;

        petcDest->cfFormat = petcSrc->cfFormat;

        petcDest->ptd      = NULL;
        if ( NULL != petcSrc->ptd )
            petcDest->ptd  = CopyTargetDevice(petcSrc->ptd);

        petcDest->dwAspect = petcSrc->dwAspect;
        petcDest->lindex   = petcSrc->lindex;
        petcDest->tymed    = petcSrc->tymed;

        bRet = sal_True;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error CopyFormatEtc" );
    }

    return bRet;
}

//-------------------------------------------------------------------------
// returns:
//  1 for exact match,
//  0 for no match,
// -1 for partial match (which is defined to mean the left is a subset
//    of the right: fewer aspects, null target device, fewer medium).
//-------------------------------------------------------------------------

sal_Int32 SAL_CALL CompareFormatEtc( const FORMATETC* pFetcLhs, const FORMATETC* pFetcRhs )
{
    sal_Int32 nMatch = FORMATETC_EXACT_MATCH;

    __try
    {
        if ( pFetcLhs == pFetcRhs )
            __leave;

        if ( ( pFetcLhs->cfFormat != pFetcRhs->cfFormat ) ||
             ( pFetcLhs->lindex   != pFetcRhs->lindex ) ||
             !CompareTargetDevice( pFetcLhs->ptd, pFetcRhs->ptd ) )
        {
            nMatch = FORMATETC_NO_MATCH;
            __leave;
        }

        if ( pFetcLhs->dwAspect == pFetcRhs->dwAspect )
            // same aspects; equal
            ;
        else if ( ( pFetcLhs->dwAspect & ~pFetcRhs->dwAspect ) != 0 )
        {
            // left not subset of aspects of right; not equal
            nMatch = FORMATETC_NO_MATCH;
            __leave;
        }
        else
            // left subset of right
            nMatch = FORMATETC_PARTIAL_MATCH;

        if ( pFetcLhs->tymed == pFetcRhs->tymed )
            // same medium flags; equal
            ;
        else if ( ( pFetcLhs->tymed & ~pFetcRhs->tymed ) != 0 )
        {
            // left not subset of medium flags of right; not equal
            nMatch = FORMATETC_NO_MATCH;
            __leave;
        }
        else
            // left subset of right
            nMatch = FORMATETC_PARTIAL_MATCH;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error CompareFormatEtc" );
        nMatch = FORMATETC_NO_MATCH;
    }

    return nMatch;
}

//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------

sal_Bool SAL_CALL CompareTargetDevice( DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE* ptdRight )
{
    sal_Bool bRet = sal_False;

    __try
    {
        if ( ptdLeft == ptdRight )
        {
            // same address of td; must be same (handles NULL case)
            bRet = sal_True;
            __leave;
        }

        // one ot the two is NULL
        if ( ( NULL == ptdRight ) || ( NULL == ptdLeft ) )
            __leave;

        if ( ptdLeft->tdSize != ptdRight->tdSize )
            __leave;

        if ( rtl_compareMemory( ptdLeft, ptdRight, ptdLeft->tdSize ) == 0 )
            bRet = sal_True;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error CompareTargetDevice" );
        bRet = sal_False;
    }

    return bRet;
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.15.14); FILE MERGED 2006/09/01 17:25:40 kaib 1.15.14.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: ImplHelper.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 17:02:53 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dtrans.hxx"

//------------------------------------------------------------------------
// includes
//------------------------------------------------------------------------

#ifndef _OSL_DIAGNOSE_H_
#include <osl/diagnose.h>
#endif

#ifndef _IMPLHELPER_HXX_
#include "ImplHelper.hxx"
#endif

#ifndef _RTL_TENCINFO_H
#include <rtl/tencinfo.h>
#endif

#ifndef _RTL_MEMORY_H_
#include <rtl/memory.h>
#endif

#include <memory>
#if defined _MSC_VER
#pragma warning(push,1)
#endif
#include <windows.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif

//------------------------------------------------------------------------
// defines
//------------------------------------------------------------------------

#define FORMATETC_EXACT_MATCH    1
#define FORMATETC_PARTIAL_MATCH -1
#define FORMATETC_NO_MATCH       0

//------------------------------------------------------------------------
// namespace directives
//------------------------------------------------------------------------

using ::rtl::OUString;
using ::rtl::OString;

//------------------------------------------------------------------------
// returns a windows codepage appropriate to the
// given mime charset parameter value
//------------------------------------------------------------------------

sal_uInt32 SAL_CALL getWinCPFromMimeCharset( const OUString& charset )
{
    sal_uInt32 winCP = GetACP( );

    if ( charset.getLength( ) )
    {
        OString osCharset(
            charset.getStr( ), charset.getLength( ), RTL_TEXTENCODING_ASCII_US );

        rtl_TextEncoding txtEnc =
            rtl_getTextEncodingFromMimeCharset( osCharset.getStr( ) );

        sal_uInt32 winChrs = rtl_getBestWindowsCharsetFromTextEncoding( txtEnc );

        CHARSETINFO chrsInf;
        sal_Bool bRet = TranslateCharsetInfo( (DWORD*)winChrs, &chrsInf, TCI_SRCCHARSET ) ?
                        sal_True : sal_False;

        // if one of the above functions fails
        // we will return the current ANSI codepage
        // of this thread
        if ( bRet )
            winCP = chrsInf.ciACP;
    }

    return winCP;
}

//--------------------------------------------------
// returns a windows codepage appropriate to the
// given locale and locale type
//--------------------------------------------------

OUString SAL_CALL getWinCPFromLocaleId( LCID lcid, LCTYPE lctype )
{
    OSL_ASSERT( IsValidLocale( lcid, LCID_SUPPORTED ) );

    // we set an default value
    OUString winCP;

    // set an default value
    sal_Unicode wcstr[10];

    if ( LOCALE_IDEFAULTCODEPAGE == lctype )
    {
        _itow( GetOEMCP( ), wcstr, 10 );
        winCP = OUString( wcstr, wcslen( wcstr ) );
    }
    else if ( LOCALE_IDEFAULTANSICODEPAGE == lctype )
    {
        _itow( GetACP( ), wcstr, 10 );
        winCP = OUString( wcstr, wcslen( wcstr ) );
    }
    else
        OSL_ASSERT( sal_False );

    // we use the GetLocaleInfoA because don't want to provide
    // a unicode wrapper function for Win9x in sal/systools
    char buff[6];
    sal_Int32 nResult = GetLocaleInfoA(
        lcid, lctype | LOCALE_USE_CP_ACP, buff, sizeof( buff ) );

    OSL_ASSERT( nResult );

    if ( nResult )
    {
        sal_Int32 len = MultiByteToWideChar(
            CP_ACP, 0, buff, -1, NULL, 0 );

        OSL_ASSERT( len > 0 );

        std::auto_ptr< sal_Unicode > lpwchBuff( new sal_Unicode[len] );

        if ( NULL != lpwchBuff.get( ) )
        {
            len = MultiByteToWideChar(
                CP_ACP, 0, buff, -1, lpwchBuff.get( ), len );

            winCP = OUString( lpwchBuff.get( ), (len - 1) );
        }
    }

    return winCP;
}

//--------------------------------------------------
// returns a mime charset parameter value appropriate
// to the given codepage, optional a prefix can be
// given, e.g. "windows-" or "cp"
//--------------------------------------------------

OUString SAL_CALL getMimeCharsetFromWinCP( sal_uInt32 cp, const OUString& aPrefix )
{
    return aPrefix + cptostr( cp );
}

//--------------------------------------------------
// returns a mime charset parameter value appropriate
// to the given locale id and locale type, optional a
// prefix can be given, e.g. "windows-" or "cp"
//--------------------------------------------------

OUString SAL_CALL getMimeCharsetFromLocaleId( LCID lcid, LCTYPE lctype, const OUString& aPrefix  )
{
    OUString charset = getWinCPFromLocaleId( lcid, lctype );
    return aPrefix + charset;
}

//------------------------------------------------------------------------
// IsOEMCP
//------------------------------------------------------------------------

sal_Bool SAL_CALL IsOEMCP( sal_uInt32 codepage )
{
    OSL_ASSERT( IsValidCodePage( codepage ) );

    sal_uInt32 arrOEMCP[] = { 437, 708, 709, 710, 720, 737,
                              775, 850, 852, 855, 857, 860,
                              861, 862, 863, 864, 865, 866,
                              869, 874, 932, 936, 949, 950, 1361 };

    for ( sal_Int8 i = 0; i < ( sizeof( arrOEMCP )/sizeof( sal_uInt32 ) ); ++i )
        if ( arrOEMCP[i] == codepage )
            return sal_True;

    return sal_False;
}

//------------------------------------------------------------------------
// converts a codepage into its string representation
//------------------------------------------------------------------------

OUString SAL_CALL cptostr( sal_uInt32 codepage )
{
    OSL_ASSERT( IsValidCodePage( codepage ) );

    sal_Unicode cpStr[6];
    _itow( codepage, cpStr, 10 );
    return OUString( cpStr, wcslen( cpStr ) );
}

//-------------------------------------------------------------------------
// OleStdDeleteTargetDevice()
//
// Purpose:
//
// Parameters:
//
// Return Value:
//    SCODE  -  S_OK if successful
//-------------------------------------------------------------------------

void SAL_CALL DeleteTargetDevice( DVTARGETDEVICE* ptd )
{
    __try
    {
        CoTaskMemFree( ptd );
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error DeleteTargetDevice" );
    }
}

//-------------------------------------------------------------------------
// OleStdCopyTargetDevice()
//
// Purpose:
//  duplicate a TARGETDEVICE struct. this function allocates memory for
//  the copy. the caller MUST free the allocated copy when done with it
//  using the standard allocator returned from CoGetMalloc.
//  (OleStdFree can be used to free the copy).
//
// Parameters:
//  ptdSrc      pointer to source TARGETDEVICE
//
// Return Value:
//    pointer to allocated copy of ptdSrc
//    if ptdSrc==NULL then retuns NULL is returned.
//    if ptdSrc!=NULL and memory allocation fails, then NULL is returned
//-------------------------------------------------------------------------

DVTARGETDEVICE* SAL_CALL CopyTargetDevice( DVTARGETDEVICE* ptdSrc )
{
    DVTARGETDEVICE* ptdDest = NULL;

    __try
    {
        if ( NULL != ptdSrc )
        {
            ptdDest = static_cast< DVTARGETDEVICE* >( CoTaskMemAlloc( ptdSrc->tdSize ) );
            rtl_copyMemory( ptdDest, ptdSrc, static_cast< size_t >( ptdSrc->tdSize ) );
        }
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
    }

    return ptdDest;
}

//-------------------------------------------------------------------------
// OleStdCopyFormatEtc()
//
// Purpose:
//  Copies the contents of a FORMATETC structure. this function takes
//  special care to copy correctly copying the pointer to the TARGETDEVICE
//  contained within the source FORMATETC structure.
//  if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy
//  of the TARGETDEVICE will be allocated for the destination of the
//  FORMATETC (petcDest).
//
//  NOTE: the caller MUST free the allocated copy of the TARGETDEVICE
//  within the destination FORMATETC when done with it
//  using the standard allocator returned from CoGetMalloc.
//  (OleStdFree can be used to free the copy).
//
// Parameters:
//  petcDest      pointer to destination FORMATETC
//  petcSrc       pointer to source FORMATETC
//
// Return Value:
//  returns TRUE if copy was successful;
//  retuns FALSE if not successful, e.g. one or both of the pointers
//  were invalid or the pointers were equal
//-------------------------------------------------------------------------

sal_Bool SAL_CALL CopyFormatEtc( LPFORMATETC petcDest, LPFORMATETC petcSrc )
{
    sal_Bool bRet = sal_False;

    __try
    {
        if ( petcDest == petcSrc )
            __leave;

        petcDest->cfFormat = petcSrc->cfFormat;

        petcDest->ptd      = NULL;
        if ( NULL != petcSrc->ptd )
            petcDest->ptd  = CopyTargetDevice(petcSrc->ptd);

        petcDest->dwAspect = petcSrc->dwAspect;
        petcDest->lindex   = petcSrc->lindex;
        petcDest->tymed    = petcSrc->tymed;

        bRet = sal_True;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error CopyFormatEtc" );
    }

    return bRet;
}

//-------------------------------------------------------------------------
// returns:
//  1 for exact match,
//  0 for no match,
// -1 for partial match (which is defined to mean the left is a subset
//    of the right: fewer aspects, null target device, fewer medium).
//-------------------------------------------------------------------------

sal_Int32 SAL_CALL CompareFormatEtc( const FORMATETC* pFetcLhs, const FORMATETC* pFetcRhs )
{
    sal_Int32 nMatch = FORMATETC_EXACT_MATCH;

    __try
    {
        if ( pFetcLhs == pFetcRhs )
            __leave;

        if ( ( pFetcLhs->cfFormat != pFetcRhs->cfFormat ) ||
             ( pFetcLhs->lindex   != pFetcRhs->lindex ) ||
             !CompareTargetDevice( pFetcLhs->ptd, pFetcRhs->ptd ) )
        {
            nMatch = FORMATETC_NO_MATCH;
            __leave;
        }

        if ( pFetcLhs->dwAspect == pFetcRhs->dwAspect )
            // same aspects; equal
            ;
        else if ( ( pFetcLhs->dwAspect & ~pFetcRhs->dwAspect ) != 0 )
        {
            // left not subset of aspects of right; not equal
            nMatch = FORMATETC_NO_MATCH;
            __leave;
        }
        else
            // left subset of right
            nMatch = FORMATETC_PARTIAL_MATCH;

        if ( pFetcLhs->tymed == pFetcRhs->tymed )
            // same medium flags; equal
            ;
        else if ( ( pFetcLhs->tymed & ~pFetcRhs->tymed ) != 0 )
        {
            // left not subset of medium flags of right; not equal
            nMatch = FORMATETC_NO_MATCH;
            __leave;
        }
        else
            // left subset of right
            nMatch = FORMATETC_PARTIAL_MATCH;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error CompareFormatEtc" );
        nMatch = FORMATETC_NO_MATCH;
    }

    return nMatch;
}

//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------

sal_Bool SAL_CALL CompareTargetDevice( DVTARGETDEVICE* ptdLeft, DVTARGETDEVICE* ptdRight )
{
    sal_Bool bRet = sal_False;

    __try
    {
        if ( ptdLeft == ptdRight )
        {
            // same address of td; must be same (handles NULL case)
            bRet = sal_True;
            __leave;
        }

        // one ot the two is NULL
        if ( ( NULL == ptdRight ) || ( NULL == ptdLeft ) )
            __leave;

        if ( ptdLeft->tdSize != ptdRight->tdSize )
            __leave;

        if ( rtl_compareMemory( ptdLeft, ptdRight, ptdLeft->tdSize ) == 0 )
            bRet = sal_True;
    }
    __except( EXCEPTION_EXECUTE_HANDLER )
    {
        OSL_ENSURE( sal_False, "Error CompareTargetDevice" );
        bRet = sal_False;
    }

    return bRet;
}
<|endoftext|>


<commit_before>#include <config.h>
#include "grid_creation.hh"

#include <dune/stuff/common/ranges.hh>
#include <dune/stuff/grid/structuredgridfactory.hh>
#include <dune/stuff/grid/information.hh>

std::pair<std::shared_ptr<Dune::Multiscale::CommonTraits::GridType>,
          std::shared_ptr<Dune::Multiscale::CommonTraits::GridType>>
Dune::Multiscale::make_grids() {
  const int dim_world = CommonTraits::GridType::dimensionworld;
  typedef FieldVector<typename CommonTraits::GridType::ctype, dim_world> CoordType;
  CoordType lowerLeft(0.0);
  CoordType upperRight(1.0);

  const auto coarse_cells = DSC_CONFIG_GET("global.macro_cells_per_dim", 8);
  array<unsigned int, dim_world> elements;
  for (const auto i : DSC::valueRange(dim_world))
    elements[i] = coarse_cells;
  auto coarse_gridptr =
      StructuredGridFactory<CommonTraits::GridType>::createCubeGrid(lowerLeft, upperRight, elements, overCoarse);

  for (const auto i : DSC::valueRange(dim_world)) {
    elements[i] = coarse_cells * DSC_CONFIG_GET("global.micro_cells_per_macrocell_dim", 8);
  }
  auto fine_gridptr = StructuredGridFactory<CommonTraits::GridType>::createCubeGrid(lowerLeft, upperRight, elements);
  return {coarse_gridptr, fine_gridptr};
}
<commit_msg>[gridCreation] compute necessary number of overlap layers for coarse grid<commit_after>#include <config.h>
#include "grid_creation.hh"

#include <dune/stuff/common/ranges.hh>
#include <dune/stuff/grid/structuredgridfactory.hh>
#include <dune/stuff/grid/information.hh>

std::pair<std::shared_ptr<Dune::Multiscale::CommonTraits::GridType>,
          std::shared_ptr<Dune::Multiscale::CommonTraits::GridType>>
Dune::Multiscale::make_grids() {
  const int dim_world = CommonTraits::GridType::dimensionworld;
  typedef FieldVector<typename CommonTraits::GridType::ctype, dim_world> CoordType;
  CoordType lowerLeft(0.0);
  CoordType upperRight(1.0);

  const auto oversamplingLayers = DSC_CONFIG_GET("msfem.oversampling_layers", 0);
  const auto microPerMacro = DSC_CONFIG_GET("msfem.micro_cells_per_macrocell_dim", 8);
  const int overlapLayers = std::ceil(double(oversamplingLayers)/double(microPerMacro));

  const auto coarse_cells = DSC_CONFIG_GET("global.macro_cells_per_dim", 8);
  array<unsigned int, dim_world> elements;
  array<unsigned int, dim_world> overCoarse;
  for (const auto i : DSC::valueRange(dim_world)) {
    elements[i] = coarse_cells;
    overCoarse[i] = overlapLayers;
  }
  auto coarse_gridptr =
      StructuredGridFactory<CommonTraits::GridType>::createCubeGrid(lowerLeft, upperRight, elements, overCoarse);

  for (const auto i : DSC::valueRange(dim_world)) {
    elements[i] = coarse_cells * DSC_CONFIG_GET("global.micro_cells_per_macrocell_dim", 8);
  }
  auto fine_gridptr = StructuredGridFactory<CommonTraits::GridType>::createCubeGrid(lowerLeft, upperRight, elements);
  return {coarse_gridptr, fine_gridptr};
}
<|endoftext|>


<commit_before>// Ouzel by Elviss Strazdins

#ifndef OUZEL_CORE_NATIVEWINDOWMACOS_HPP
#define OUZEL_CORE_NATIVEWINDOWMACOS_HPP

#include <CoreGraphics/CGGeometry.h>
#include <CoreGraphics/CoreGraphics.h>

#ifdef __OBJC__
#  import <Cocoa/Cocoa.h>
typedef NSWindow* NSWindowPtr;
typedef NSView* NSViewPtr;
typedef id<NSWindowDelegate> NSWindowDelegatePtr;
typedef NSScreen* NSScreenPtr;
#else
#  include <objc/NSObjCRuntime.h>
typedef id NSWindowPtr;
typedef id NSViewPtr;
typedef id NSWindowDelegatePtr;
typedef id NSScreenPtr;
typedef std::uint32_t CGDirectDisplayID;
#endif

#include "../NativeWindow.hpp"
#include "../../graphics/Graphics.hpp"

namespace ouzel::core::macos
{
    class NativeWindow final: public core::NativeWindow
    {
    public:
        NativeWindow(const math::Size<std::uint32_t, 2>& newSize,
                     bool newResizable,
                     bool newFullscreen,
                     bool newExclusiveFullscreen,
                     const std::string& newTitle,
                     graphics::Driver graphicsDriver,
                     bool newHighDpi);
        ~NativeWindow() override;

        void close();

        void setSize(const math::Size<std::uint32_t, 2>& newSize);
        void setFullscreen(bool newFullscreen);
        void setTitle(const std::string& newTitle);
        void bringToFront();
        void show();
        void hide();
        void minimize();
        void maximize();
        void restore();

        void handleResize();
        void handleClose();
        void handleMinituarize();
        void handleDeminituarize();
        void handleFullscreenChange(bool newFullscreen);
        void handleScaleFactorChange();
        void handleScreenChange();
        void handleBecomeKeyChange();
        void handleResignKeyChange();

        auto getNativeWindow() const noexcept { return window; }
        auto getNativeView() const noexcept { return view; }
        auto getScreen() const noexcept { return screen; }
        auto getDisplayId() const noexcept { return displayId; }

    private:
        void executeCommand(const Command& command) final;

        NSWindowPtr window = nil;
        NSViewPtr view = nil;
        NSWindowDelegatePtr windowDelegate = nil;
        NSScreenPtr screen = nil;
        CGDirectDisplayID displayId = 0;
        NSUInteger windowStyleMask = 0;
        CGRect windowRect;
    };
}

#endif // OUZEL_CORE_NATIVEWINDOWMACOS_HPP
<commit_msg>Include only Driver.hpp<commit_after>// Ouzel by Elviss Strazdins

#ifndef OUZEL_CORE_NATIVEWINDOWMACOS_HPP
#define OUZEL_CORE_NATIVEWINDOWMACOS_HPP

#include <CoreGraphics/CGGeometry.h>
#include <CoreGraphics/CoreGraphics.h>

#ifdef __OBJC__
#  import <Cocoa/Cocoa.h>
typedef NSWindow* NSWindowPtr;
typedef NSView* NSViewPtr;
typedef id<NSWindowDelegate> NSWindowDelegatePtr;
typedef NSScreen* NSScreenPtr;
#else
#  include <objc/NSObjCRuntime.h>
typedef id NSWindowPtr;
typedef id NSViewPtr;
typedef id NSWindowDelegatePtr;
typedef id NSScreenPtr;
typedef std::uint32_t CGDirectDisplayID;
#endif

#include "../NativeWindow.hpp"
#include "../../graphics/Driver.hpp"

namespace ouzel::core::macos
{
    class NativeWindow final: public core::NativeWindow
    {
    public:
        NativeWindow(const math::Size<std::uint32_t, 2>& newSize,
                     bool newResizable,
                     bool newFullscreen,
                     bool newExclusiveFullscreen,
                     const std::string& newTitle,
                     graphics::Driver graphicsDriver,
                     bool newHighDpi);
        ~NativeWindow() override;

        void close();

        void setSize(const math::Size<std::uint32_t, 2>& newSize);
        void setFullscreen(bool newFullscreen);
        void setTitle(const std::string& newTitle);
        void bringToFront();
        void show();
        void hide();
        void minimize();
        void maximize();
        void restore();

        void handleResize();
        void handleClose();
        void handleMinituarize();
        void handleDeminituarize();
        void handleFullscreenChange(bool newFullscreen);
        void handleScaleFactorChange();
        void handleScreenChange();
        void handleBecomeKeyChange();
        void handleResignKeyChange();

        auto getNativeWindow() const noexcept { return window; }
        auto getNativeView() const noexcept { return view; }
        auto getScreen() const noexcept { return screen; }
        auto getDisplayId() const noexcept { return displayId; }

    private:
        void executeCommand(const Command& command) final;

        NSWindowPtr window = nil;
        NSViewPtr view = nil;
        NSWindowDelegatePtr windowDelegate = nil;
        NSScreenPtr screen = nil;
        CGDirectDisplayID displayId = 0;
        NSUInteger windowStyleMask = 0;
        CGRect windowRect;
    };
}

#endif // OUZEL_CORE_NATIVEWINDOWMACOS_HPP
<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkScatterPlotMatrix.cxx

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

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

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

#include "vtkScatterPlotMatrix.h"

#include "vtkTable.h"
#include "vtkFloatArray.h"
#include "vtkIntArray.h"
#include "vtkChartXY.h"
#include "vtkPlot.h"
#include "vtkAxis.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"
#include "vtkNew.h"
#include "vtkMathUtilities.h"
#include "vtkObjectFactory.h"

class vtkScatterPlotMatrix::PIMPL
{
public:
  PIMPL() : VisibleColumnsModified(true), BigChart(NULL)
  {
  }

  ~PIMPL()
  {
  }

  vtkNew<vtkTable> Histogram;
  bool VisibleColumnsModified;
  vtkChart* BigChart;
};

namespace
{

int NumberOfBins = 10;

// This is just here for now - quick and dirty historgram calculations...
bool PopulateHistograms(vtkTable *input, vtkTable *output, vtkStringArray *s)
{
  // The output table will have the twice the number of columns, they will be
  // the x and y for input column. This is the bin centers, and the population.
  for (vtkIdType i = output->GetNumberOfColumns() - 1; i >= 0; --i)
    {
    output->RemoveColumn(i);
    }
  for (vtkIdType i = 0; i < s->GetNumberOfTuples(); ++i)
    {
    double minmax[2] = { 0.0, 0.0 };
    vtkStdString name(s->GetValue(i));
    vtkDataArray *in =
        vtkDataArray::SafeDownCast(input->GetColumnByName(name.c_str()));
    if (in)
      {
      // The bin values are the centers, extending +/- half an inc either side
      in->GetRange(minmax);
      if (minmax[0] == minmax[1])
        {
        minmax[1] = minmax[0] + 1.0;
        }
      double inc = (minmax[1] - minmax[0]) / NumberOfBins;
      double halfInc = inc / 2.0;
      vtkNew<vtkFloatArray> extents;
      extents->SetName(vtkStdString(name + "_extents").c_str());
      extents->SetNumberOfTuples(NumberOfBins);
      float *centers = static_cast<float *>(extents->GetVoidPointer(0));
      for (int j = 0; j < NumberOfBins; ++j)
        {
        extents->SetValue(j, minmax[0] + j * inc);
        }
      vtkNew<vtkIntArray> populations;
      populations->SetName(vtkStdString(name + "_pops").c_str());
      populations->SetNumberOfTuples(NumberOfBins);
      int *pops = static_cast<int *>(populations->GetVoidPointer(0));
      for (int k = 0; k < NumberOfBins; ++k)
        {
        pops[k] = 0;
        }
      for (vtkIdType j = 0; j < in->GetNumberOfTuples(); ++j)
        {
        double v(0.0);
        in->GetTuple(j, &v);
        for (int k = 0; k < NumberOfBins; ++k)
          {
          if (vtkMathUtilities::FuzzyCompare(v, double(centers[k]), halfInc))
            {
            ++pops[k];
            break;
            }
          }
        }
      output->AddColumn(extents.GetPointer());
      output->AddColumn(populations.GetPointer());
      }
    }
  return true;
}
}

vtkStandardNewMacro(vtkScatterPlotMatrix)

vtkScatterPlotMatrix::vtkScatterPlotMatrix()
{
  this->Private = new PIMPL;
}

vtkScatterPlotMatrix::~vtkScatterPlotMatrix()
{
  delete this->Private;
}

void vtkScatterPlotMatrix::Update()
{
  if (this->Private->VisibleColumnsModified)
    {
    // We need to handle layout changes due to modified visibility.
    // Build up our histograms data before updating the layout.
    PopulateHistograms(this->Input.GetPointer(),
                       this->Private->Histogram.GetPointer(),
                       this->VisibleColumns.GetPointer());
    this->UpdateLayout();
    this->Private->VisibleColumnsModified = false;
    }
}

bool vtkScatterPlotMatrix::Paint(vtkContext2D *painter)
{
  this->Update();
  return Superclass::Paint(painter);
}

bool vtkScatterPlotMatrix::SetActivePlot(const vtkVector2i &pos)
{
  if (pos.X() + pos.Y() + 1 < this->Size.X() && pos.X() < this->Size.X() &&
      pos.Y() < this->Size.Y())
    {
    // The supplied index is valid (in the lower quadrant).
    this->ActivePlot = pos;
    if (this->Private->BigChart)
      {
      vtkPlot *plot = this->Private->BigChart->GetPlot(0);
      if (!plot)
        {
        plot = this->Private->BigChart->AddPlot(vtkChart::POINTS);
        vtkChartXY *xy = vtkChartXY::SafeDownCast(this->Private->BigChart);
        if (xy)
          {
          xy->SetPlotCorner(plot, 2);
          }
        }
      plot->SetInput(this->Input.GetPointer(),
                     this->VisibleColumns->GetValue(pos.X()),
                     this->VisibleColumns->GetValue(this->Size.X() -
                                                    pos.Y() - 1));
      }
    return true;
    }
  else
    {
    return false;
    }
}

vtkVector2i vtkScatterPlotMatrix::GetActivePlot()
{
  return this->ActivePlot;
}

void vtkScatterPlotMatrix::SetInput(vtkTable *table)
{
  if (this->Input != table)
    {
    // Set the input, then update the size of the scatter plot matrix, set
    // their inputs and all the other stuff needed.
    this->Input = table;
    this->Modified();

    if (table == NULL)
      {
      this->SetSize(vtkVector2i(0, 0));
      this->SetColumnVisibilityAll(true);
      return;
      }

    int n = static_cast<int>(this->Input->GetNumberOfColumns());
    this->SetColumnVisibilityAll(true);
    this->SetSize(vtkVector2i(n, n));
    }
}

void vtkScatterPlotMatrix::SetColumnVisibility(const vtkStdString &name,
                                               bool visible)
{
  if (visible)
    {
    for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
      {
      if (this->VisibleColumns->GetValue(i) == name)
        {
        // Already there, nothing more needs to be done
        return;
        }
      }
    // Add the column to the end of the list
    this->VisibleColumns->InsertNextValue(name);
    this->Private->VisibleColumnsModified = true;
    this->SetSize(vtkVector2i(this->VisibleColumns->GetNumberOfTuples(),
                              this->VisibleColumns->GetNumberOfTuples()));
    this->Modified();
    }
  else
    {
    // Remove the value if present
    for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
      {
      if (this->VisibleColumns->GetValue(i) == name)
        {
        // Move all the later elements down by one, and reduce the size
        while (i < this->VisibleColumns->GetNumberOfTuples()-1)
          {
          this->VisibleColumns->SetValue(i,
                                         this->VisibleColumns->GetValue(i+1));
          ++i;
          }
        this->VisibleColumns->SetNumberOfTuples(
            this->VisibleColumns->GetNumberOfTuples()-1);
        this->SetSize(vtkVector2i(this->VisibleColumns->GetNumberOfTuples(),
                                  this->VisibleColumns->GetNumberOfTuples()));
        this->Private->VisibleColumnsModified = true;
        this->Modified();
        return;
        }
      }
    }
}

bool vtkScatterPlotMatrix::GetColumnVisibility(const vtkStdString &name)
{
  for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
    {
    if (this->VisibleColumns->GetValue(i) == name)
      {
      return true;
      }
    }
  return false;
}

void vtkScatterPlotMatrix::SetColumnVisibilityAll(bool visible)
{
  if (visible && this->Input)
    {
    vtkIdType n = this->Input->GetNumberOfColumns();
    this->VisibleColumns->SetNumberOfTuples(n);
    for (vtkIdType i = 0; i < n; ++i)
      {
      this->VisibleColumns->SetValue(i, this->Input->GetColumnName(i));
      }
    }
  else
    {
    this->SetSize(vtkVector2i(0, 0));
    this->VisibleColumns->SetNumberOfTuples(0);
    }

  this->Private->VisibleColumnsModified = true;
}

vtkStringArray* vtkScatterPlotMatrix::GetVisibleColumns()
{
  return this->VisibleColumns.GetPointer();
}

void vtkScatterPlotMatrix::UpdateLayout()
{
  // We want scatter plots on the lower-left triangle, then histograms along
  // the diagonal and a big plot in the top-right. The basic layout is,
  //
  // 0 H   +++
  // 1 S H +++
  // 2 S S H
  // 3 S S S H
  //   0 1 2 3
  //
  // Where the indices are those of the columns. The indices of the charts
  // originate in the bottom-left.
  int n = this->Size.X();
  for (int i = 0; i < n; ++i)
    {
    for (int j = 0; j < n; ++j)
      {
      vtkVector2i pos(i, j);
      if (i + j + 1 < n)
        {
        // Lower-left triangle - scatter plots.
        vtkPlot *plot = this->GetChart(pos)->AddPlot(vtkChart::POINTS);
        plot->SetInput(this->Input.GetPointer(), i, n - j - 1);
        }
      else if (i == n - j - 1)
        {
        // We are on the diagonal - need a histogram plot.
        vtkPlot *plot = this->GetChart(pos)->AddPlot(vtkChart::BAR);
        vtkStdString name(this->VisibleColumns->GetValue(i));
        plot->SetInput(this->Private->Histogram.GetPointer(),
                       name + "_extents", name + "_pops");
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::TOP);
        axis->SetTitle(name.c_str());
        if (i != n - 1)
          {
          axis->SetBehavior(vtkAxis::FIXED);
          }
        // Set the plot corner to the top-right
        vtkChartXY *xy = vtkChartXY::SafeDownCast(this->GetChart(pos));
        if (xy)
          {
          xy->SetPlotCorner(plot, 2);
          }
        }
      else if (i == static_cast<int>(n / 2.0) + n % 2 && i == j)
        {
        // This big plot in the top-right
        this->Private->BigChart = this->GetChart(pos);
        this->SetChartSpan(pos, vtkVector2i(n - i, n - j));
        this->SetActivePlot(vtkVector2i(0, n - 2));
        }
      // Only show bottom axis label for bottom plots
      if (j > 0)
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::BOTTOM);
        axis->SetTitle("");
        axis->SetLabelsVisible(false);
        axis->SetBehavior(vtkAxis::FIXED);
        }
      else
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::BOTTOM);
        axis->SetTitle(this->VisibleColumns->GetValue(i));
        this->AttachAxisRangeListener(axis);
        }
      // Only show the left axis labels for left-most plots
      if (i > 0)
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::LEFT);
        axis->SetTitle("");
        axis->SetLabelsVisible(false);
        axis->SetBehavior(vtkAxis::FIXED);
        }
      else
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::LEFT);
        axis->SetTitle(this->VisibleColumns->GetValue(n - j - 1));
        this->AttachAxisRangeListener(axis);
        }
      }
    }
}

void vtkScatterPlotMatrix::AttachAxisRangeListener(vtkAxis* axis)
{
  axis->AddObserver(vtkChart::UpdateRange, this,
                    &vtkScatterPlotMatrix::AxisRangeForwarderCallback);
}

void vtkScatterPlotMatrix::AxisRangeForwarderCallback(vtkObject*,
                                                      unsigned long, void*)
{
  // Only set on the end axes, and propagated to all other matching axes.
  double r[2];
  int n = this->GetSize().X() - 1;
  for (int i = 0; i < n; ++i)
    {
    this->GetChart(vtkVector2i(i, 0))->GetAxis(vtkAxis::BOTTOM)->GetRange(r);
    for (int j = 1; j < n - i; ++j)
      {
      this->GetChart(vtkVector2i(i, j))->GetAxis(vtkAxis::BOTTOM)->SetRange(r);
      }
    this->GetChart(vtkVector2i(i, n-i))->GetAxis(vtkAxis::TOP)->SetRange(r);
    this->GetChart(vtkVector2i(0, i))->GetAxis(vtkAxis::LEFT)->GetRange(r);
    for (int j = 1; j < n - i; ++j)
      {
      this->GetChart(vtkVector2i(j, i))->GetAxis(vtkAxis::LEFT)->SetRange(r);
      }
    }
}

void vtkScatterPlotMatrix::PrintSelf(ostream &os, vtkIndent indent)
{
  Superclass::PrintSelf(os, indent);
}
<commit_msg>Add check for empty table to vtkScatterPlotMatrix::SetInput()<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkScatterPlotMatrix.cxx

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

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

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

#include "vtkScatterPlotMatrix.h"

#include "vtkTable.h"
#include "vtkFloatArray.h"
#include "vtkIntArray.h"
#include "vtkChartXY.h"
#include "vtkPlot.h"
#include "vtkAxis.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"
#include "vtkNew.h"
#include "vtkMathUtilities.h"
#include "vtkObjectFactory.h"

class vtkScatterPlotMatrix::PIMPL
{
public:
  PIMPL() : VisibleColumnsModified(true), BigChart(NULL)
  {
  }

  ~PIMPL()
  {
  }

  vtkNew<vtkTable> Histogram;
  bool VisibleColumnsModified;
  vtkChart* BigChart;
};

namespace
{

int NumberOfBins = 10;

// This is just here for now - quick and dirty historgram calculations...
bool PopulateHistograms(vtkTable *input, vtkTable *output, vtkStringArray *s)
{
  // The output table will have the twice the number of columns, they will be
  // the x and y for input column. This is the bin centers, and the population.
  for (vtkIdType i = output->GetNumberOfColumns() - 1; i >= 0; --i)
    {
    output->RemoveColumn(i);
    }
  for (vtkIdType i = 0; i < s->GetNumberOfTuples(); ++i)
    {
    double minmax[2] = { 0.0, 0.0 };
    vtkStdString name(s->GetValue(i));
    vtkDataArray *in =
        vtkDataArray::SafeDownCast(input->GetColumnByName(name.c_str()));
    if (in)
      {
      // The bin values are the centers, extending +/- half an inc either side
      in->GetRange(minmax);
      if (minmax[0] == minmax[1])
        {
        minmax[1] = minmax[0] + 1.0;
        }
      double inc = (minmax[1] - minmax[0]) / NumberOfBins;
      double halfInc = inc / 2.0;
      vtkNew<vtkFloatArray> extents;
      extents->SetName(vtkStdString(name + "_extents").c_str());
      extents->SetNumberOfTuples(NumberOfBins);
      float *centers = static_cast<float *>(extents->GetVoidPointer(0));
      for (int j = 0; j < NumberOfBins; ++j)
        {
        extents->SetValue(j, minmax[0] + j * inc);
        }
      vtkNew<vtkIntArray> populations;
      populations->SetName(vtkStdString(name + "_pops").c_str());
      populations->SetNumberOfTuples(NumberOfBins);
      int *pops = static_cast<int *>(populations->GetVoidPointer(0));
      for (int k = 0; k < NumberOfBins; ++k)
        {
        pops[k] = 0;
        }
      for (vtkIdType j = 0; j < in->GetNumberOfTuples(); ++j)
        {
        double v(0.0);
        in->GetTuple(j, &v);
        for (int k = 0; k < NumberOfBins; ++k)
          {
          if (vtkMathUtilities::FuzzyCompare(v, double(centers[k]), halfInc))
            {
            ++pops[k];
            break;
            }
          }
        }
      output->AddColumn(extents.GetPointer());
      output->AddColumn(populations.GetPointer());
      }
    }
  return true;
}
}

vtkStandardNewMacro(vtkScatterPlotMatrix)

vtkScatterPlotMatrix::vtkScatterPlotMatrix()
{
  this->Private = new PIMPL;
}

vtkScatterPlotMatrix::~vtkScatterPlotMatrix()
{
  delete this->Private;
}

void vtkScatterPlotMatrix::Update()
{
  if (this->Private->VisibleColumnsModified)
    {
    // We need to handle layout changes due to modified visibility.
    // Build up our histograms data before updating the layout.
    PopulateHistograms(this->Input.GetPointer(),
                       this->Private->Histogram.GetPointer(),
                       this->VisibleColumns.GetPointer());
    this->UpdateLayout();
    this->Private->VisibleColumnsModified = false;
    }
}

bool vtkScatterPlotMatrix::Paint(vtkContext2D *painter)
{
  this->Update();
  return Superclass::Paint(painter);
}

bool vtkScatterPlotMatrix::SetActivePlot(const vtkVector2i &pos)
{
  if (pos.X() + pos.Y() + 1 < this->Size.X() && pos.X() < this->Size.X() &&
      pos.Y() < this->Size.Y())
    {
    // The supplied index is valid (in the lower quadrant).
    this->ActivePlot = pos;
    if (this->Private->BigChart)
      {
      vtkPlot *plot = this->Private->BigChart->GetPlot(0);
      if (!plot)
        {
        plot = this->Private->BigChart->AddPlot(vtkChart::POINTS);
        vtkChartXY *xy = vtkChartXY::SafeDownCast(this->Private->BigChart);
        if (xy)
          {
          xy->SetPlotCorner(plot, 2);
          }
        }
      plot->SetInput(this->Input.GetPointer(),
                     this->VisibleColumns->GetValue(pos.X()),
                     this->VisibleColumns->GetValue(this->Size.X() -
                                                    pos.Y() - 1));
      }
    return true;
    }
  else
    {
    return false;
    }
}

vtkVector2i vtkScatterPlotMatrix::GetActivePlot()
{
  return this->ActivePlot;
}

void vtkScatterPlotMatrix::SetInput(vtkTable *table)
{
  if(table && table->GetNumberOfRows() == 0)
    {
    // do nothing if the table is emtpy
    return;
    }

  if (this->Input != table)
    {
    // Set the input, then update the size of the scatter plot matrix, set
    // their inputs and all the other stuff needed.
    this->Input = table;
    this->Modified();

    if (table == NULL)
      {
      this->SetSize(vtkVector2i(0, 0));
      this->SetColumnVisibilityAll(true);
      return;
      }

    int n = static_cast<int>(this->Input->GetNumberOfColumns());
    this->SetColumnVisibilityAll(true);
    this->SetSize(vtkVector2i(n, n));
    }
}

void vtkScatterPlotMatrix::SetColumnVisibility(const vtkStdString &name,
                                               bool visible)
{
  if (visible)
    {
    for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
      {
      if (this->VisibleColumns->GetValue(i) == name)
        {
        // Already there, nothing more needs to be done
        return;
        }
      }
    // Add the column to the end of the list
    this->VisibleColumns->InsertNextValue(name);
    this->Private->VisibleColumnsModified = true;
    this->SetSize(vtkVector2i(this->VisibleColumns->GetNumberOfTuples(),
                              this->VisibleColumns->GetNumberOfTuples()));
    this->Modified();
    }
  else
    {
    // Remove the value if present
    for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
      {
      if (this->VisibleColumns->GetValue(i) == name)
        {
        // Move all the later elements down by one, and reduce the size
        while (i < this->VisibleColumns->GetNumberOfTuples()-1)
          {
          this->VisibleColumns->SetValue(i,
                                         this->VisibleColumns->GetValue(i+1));
          ++i;
          }
        this->VisibleColumns->SetNumberOfTuples(
            this->VisibleColumns->GetNumberOfTuples()-1);
        this->SetSize(vtkVector2i(this->VisibleColumns->GetNumberOfTuples(),
                                  this->VisibleColumns->GetNumberOfTuples()));
        this->Private->VisibleColumnsModified = true;
        this->Modified();
        return;
        }
      }
    }
}

bool vtkScatterPlotMatrix::GetColumnVisibility(const vtkStdString &name)
{
  for (vtkIdType i = 0; i < this->VisibleColumns->GetNumberOfTuples(); ++i)
    {
    if (this->VisibleColumns->GetValue(i) == name)
      {
      return true;
      }
    }
  return false;
}

void vtkScatterPlotMatrix::SetColumnVisibilityAll(bool visible)
{
  if (visible && this->Input)
    {
    vtkIdType n = this->Input->GetNumberOfColumns();
    this->VisibleColumns->SetNumberOfTuples(n);
    for (vtkIdType i = 0; i < n; ++i)
      {
      this->VisibleColumns->SetValue(i, this->Input->GetColumnName(i));
      }
    }
  else
    {
    this->SetSize(vtkVector2i(0, 0));
    this->VisibleColumns->SetNumberOfTuples(0);
    }

  this->Private->VisibleColumnsModified = true;
}

vtkStringArray* vtkScatterPlotMatrix::GetVisibleColumns()
{
  return this->VisibleColumns.GetPointer();
}

void vtkScatterPlotMatrix::UpdateLayout()
{
  // We want scatter plots on the lower-left triangle, then histograms along
  // the diagonal and a big plot in the top-right. The basic layout is,
  //
  // 0 H   +++
  // 1 S H +++
  // 2 S S H
  // 3 S S S H
  //   0 1 2 3
  //
  // Where the indices are those of the columns. The indices of the charts
  // originate in the bottom-left.
  int n = this->Size.X();
  for (int i = 0; i < n; ++i)
    {
    for (int j = 0; j < n; ++j)
      {
      vtkVector2i pos(i, j);
      if (i + j + 1 < n)
        {
        // Lower-left triangle - scatter plots.
        vtkPlot *plot = this->GetChart(pos)->AddPlot(vtkChart::POINTS);
        plot->SetInput(this->Input.GetPointer(), i, n - j - 1);
        }
      else if (i == n - j - 1)
        {
        // We are on the diagonal - need a histogram plot.
        vtkPlot *plot = this->GetChart(pos)->AddPlot(vtkChart::BAR);
        vtkStdString name(this->VisibleColumns->GetValue(i));
        plot->SetInput(this->Private->Histogram.GetPointer(),
                       name + "_extents", name + "_pops");
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::TOP);
        axis->SetTitle(name.c_str());
        if (i != n - 1)
          {
          axis->SetBehavior(vtkAxis::FIXED);
          }
        // Set the plot corner to the top-right
        vtkChartXY *xy = vtkChartXY::SafeDownCast(this->GetChart(pos));
        if (xy)
          {
          xy->SetPlotCorner(plot, 2);
          }
        }
      else if (i == static_cast<int>(n / 2.0) + n % 2 && i == j)
        {
        // This big plot in the top-right
        this->Private->BigChart = this->GetChart(pos);
        this->SetChartSpan(pos, vtkVector2i(n - i, n - j));
        this->SetActivePlot(vtkVector2i(0, n - 2));
        }
      // Only show bottom axis label for bottom plots
      if (j > 0)
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::BOTTOM);
        axis->SetTitle("");
        axis->SetLabelsVisible(false);
        axis->SetBehavior(vtkAxis::FIXED);
        }
      else
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::BOTTOM);
        axis->SetTitle(this->VisibleColumns->GetValue(i));
        this->AttachAxisRangeListener(axis);
        }
      // Only show the left axis labels for left-most plots
      if (i > 0)
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::LEFT);
        axis->SetTitle("");
        axis->SetLabelsVisible(false);
        axis->SetBehavior(vtkAxis::FIXED);
        }
      else
        {
        vtkAxis *axis = this->GetChart(pos)->GetAxis(vtkAxis::LEFT);
        axis->SetTitle(this->VisibleColumns->GetValue(n - j - 1));
        this->AttachAxisRangeListener(axis);
        }
      }
    }
}

void vtkScatterPlotMatrix::AttachAxisRangeListener(vtkAxis* axis)
{
  axis->AddObserver(vtkChart::UpdateRange, this,
                    &vtkScatterPlotMatrix::AxisRangeForwarderCallback);
}

void vtkScatterPlotMatrix::AxisRangeForwarderCallback(vtkObject*,
                                                      unsigned long, void*)
{
  // Only set on the end axes, and propagated to all other matching axes.
  double r[2];
  int n = this->GetSize().X() - 1;
  for (int i = 0; i < n; ++i)
    {
    this->GetChart(vtkVector2i(i, 0))->GetAxis(vtkAxis::BOTTOM)->GetRange(r);
    for (int j = 1; j < n - i; ++j)
      {
      this->GetChart(vtkVector2i(i, j))->GetAxis(vtkAxis::BOTTOM)->SetRange(r);
      }
    this->GetChart(vtkVector2i(i, n-i))->GetAxis(vtkAxis::TOP)->SetRange(r);
    this->GetChart(vtkVector2i(0, i))->GetAxis(vtkAxis::LEFT)->GetRange(r);
    for (int j = 1; j < n - i; ++j)
      {
      this->GetChart(vtkVector2i(j, i))->GetAxis(vtkAxis::LEFT)->SetRange(r);
      }
    }
}

void vtkScatterPlotMatrix::PrintSelf(ostream &os, vtkIndent indent)
{
  Superclass::PrintSelf(os, indent);
}
<|endoftext|>