<commit_before>#include "property_grid.h"
#include "asset_browser.h"
#include "core/crc32.h"
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "engine/property_descriptor.h"
#include "ocornut-imgui/imgui.h"
#include "string_builder.h"
#include "terrain_editor.h"

const char* PropertyGrid::getComponentTypeName(Lumix::ComponentUID cmp) const
{
	auto& engine = m_editor.getEngine();
	for (int i = 0; i < engine.getComponentTypesCount(); ++i)
	{
		if (cmp.type ==
			Lumix::crc32(engine.getComponentTypeID(i)))
		{
			return engine.getComponentTypeName(i);
		}
	}
	return "Unknown";
}

PropertyGrid::PropertyGrid(Lumix::WorldEditor& editor, AssetBrowser& asset_browser)
	: m_is_opened(true)
	, m_editor(editor)
	, m_asset_browser(asset_browser)
{
	m_filter[0] = '\0';
	m_terrain_editor = editor.getAllocator().newObject<TerrainEditor>(editor);
}

PropertyGrid::~PropertyGrid()
{
	m_editor.getAllocator().deleteObject(m_terrain_editor);
}

bool PropertyGrid::getResourcePath(char* buf, int max_size, uint32_t resource_type)
{
	ImGui::InputText("Filter", m_filter, sizeof(m_filter));

	auto type = m_asset_browser.getTypeFromResourceManagerType(resource_type);
	for (auto unv : m_asset_browser.getResources(type))
	{
		if (m_filter[0] != '\0' && strstr(unv.c_str(), m_filter) == nullptr) continue;

		if (ImGui::Selectable(unv.c_str(), false))
		{
			Lumix::copyString(buf, max_size, unv.c_str());
			ImGui::EndPopup();
			return true;
		}
	}

	ImGui::EndPopup();
	return false;
}

void PropertyGrid::showProperty(Lumix::IPropertyDescriptor& desc, int index, Lumix::ComponentUID cmp)
{
	Lumix::OutputBlob stream(m_editor.getAllocator());
	if (index < 0)
		desc.get(cmp, stream);
	else
		desc.get(cmp, index, stream);
	Lumix::InputBlob tmp(stream);

	switch (desc.getType())
	{
	case Lumix::IPropertyDescriptor::DECIMAL:
	{
		float f;
		tmp.read(f);
		auto& d = static_cast<Lumix::IDecimalPropertyDescriptor&>(desc);
		if ((d.getMax() - d.getMin()) / d.getStep() <= 100)
		{
			if (ImGui::SliderFloat(desc.getName(), &f, d.getMin(), d.getMax()))
			{
				m_editor.setProperty(cmp.type, index, desc, &f, sizeof(f));
			}
		}
		else
		{
			if (ImGui::DragFloat(desc.getName(), &f, d.getStep(), d.getMin(), d.getMax()))
			{
				m_editor.setProperty(cmp.type, index, desc, &f, sizeof(f));
			}
		}
		break;
	}
	case Lumix::IPropertyDescriptor::INTEGER:
	{
		int i;
		tmp.read(i);
		if (ImGui::DragInt(desc.getName(), &i))
		{
			m_editor.setProperty(cmp.type, index, desc, &i, sizeof(i));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::BOOL:
	{
		bool b;
		tmp.read(b);
		if (ImGui::Checkbox(desc.getName(), &b))
		{
			m_editor.setProperty(cmp.type, index, desc, &b, sizeof(b));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::COLOR:
	{
		Lumix::Vec3 v;
		tmp.read(v);
		if (ImGui::ColorEdit3(desc.getName(), &v.x))
		{
			m_editor.setProperty(cmp.type, index, desc, &v, sizeof(v));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::VEC3:
	{
		Lumix::Vec3 v;
		tmp.read(v);
		if (ImGui::DragFloat3(desc.getName(), &v.x))
		{
			m_editor.setProperty(cmp.type, index, desc, &v, sizeof(v));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::VEC4:
	{
		Lumix::Vec4 v;
		tmp.read(v);
		if (ImGui::DragFloat4(desc.getName(), &v.x))
		{
			m_editor.setProperty(cmp.type, index, desc, &v, sizeof(v));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::RESOURCE:
	{
		char buf[1024];
		Lumix::copyString(buf, sizeof(buf), (const char*)stream.getData());
		if (ImGui::InputText("", buf, sizeof(buf)))
		{
			m_editor.setProperty(cmp.type, index, desc, buf, strlen(buf) + 1);
		}
		ImGui::SameLine();
		if (ImGui::Button("Select"))
			ImGui::OpenPopup("SelectResourcePopup");
		if (ImGui::BeginPopup("SelectResourcePopup"))
		{
			auto& resource_descriptor = dynamic_cast<Lumix::ResourcePropertyDescriptorBase&>(desc);
			if (getResourcePath(buf, sizeof(buf), resource_descriptor.getResourceType()))
			{
				m_editor.setProperty(cmp.type, index, desc, buf, strlen(buf) + 1);
			}
		}
		break;
	}
	case Lumix::IPropertyDescriptor::STRING:
	case Lumix::IPropertyDescriptor::FILE:
	{
		char buf[1024];
		Lumix::copyString(buf, sizeof(buf), (const char*)stream.getData());
		if (ImGui::InputText(desc.getName(), buf, sizeof(buf)))
		{
			m_editor.setProperty(cmp.type, index, desc, buf, strlen(buf) + 1);
		}
		break;
	}
	case Lumix::IPropertyDescriptor::ARRAY:
		showArrayProperty(cmp, static_cast<Lumix::IArrayDescriptor&>(desc));
		break;
	default:
		ASSERT(false);
		break;
	}
}

void PropertyGrid::showArrayProperty(Lumix::ComponentUID cmp, Lumix::IArrayDescriptor& desc)
{
	if (!ImGui::CollapsingHeader(desc.getName(), nullptr, true, true)) return;

	int count = desc.getCount(cmp);
	if (ImGui::Button("Add"))
	{
		desc.addArrayItem(cmp, count);
	}
	count = desc.getCount(cmp);

	for (int i = 0; i < count; ++i)
	{
		char tmp[10];
		Lumix::toCString(i, tmp, sizeof(tmp));
		if (ImGui::TreeNode(tmp))
		{
			ImGui::SameLine();
			if (ImGui::Button("Remove"))
			{
				desc.removeArrayItem(cmp, i);
				--i;
				count = desc.getCount(cmp);
				ImGui::TreePop();
				continue;
			}

			for (int j = 0; j < desc.getChildren().size(); ++j)
			{
				auto* child = desc.getChildren()[j];
				showProperty(*child, i, cmp);
			}
			ImGui::TreePop();
		}
	}
}

void PropertyGrid::showComponentProperties(Lumix::ComponentUID cmp)
{
	if (!ImGui::CollapsingHeader(
		getComponentTypeName(cmp), nullptr, true, true))
		return;
	if (ImGui::Button(
		StringBuilder<30>("Remove component##", cmp.type)))
	{
		m_editor.destroyComponent(cmp);
		return;
	}

	auto& descs = m_editor.getEngine().getPropertyDescriptors(cmp.type);

	for (auto* desc : descs)
	{
		showProperty(*desc, -1, cmp);
	}

	if (cmp.type == Lumix::crc32("terrain"))
	{
		m_terrain_editor->setComponent(cmp);
		m_terrain_editor->onGui();
	}
}

void PropertyGrid::showCoreProperties(Lumix::Entity entity)
{
	char name[256];
	const char* tmp = m_editor.getUniverse()->getEntityName(entity);
	Lumix::copyString(name, sizeof(name), tmp);
	if (ImGui::InputText("Name", name, sizeof(name)))
	{
		m_editor.setEntityName(entity, name);
	}

	auto pos = m_editor.getUniverse()->getPosition(entity);
	if (ImGui::DragFloat3("Position", &pos.x))
	{
		m_editor.setEntitiesPositions(&entity, &pos, 1);
	}

	auto rot = m_editor.getUniverse()->getRotation(entity);
	if (ImGui::DragFloat4("Rotation", &rot.x))
	{
		m_editor.setEntitiesRotations(&entity, &rot, 1);
	}

	float scale = m_editor.getUniverse()->getScale(entity);
	if (ImGui::DragFloat("Scale", &scale, 0.1f))
	{
		m_editor.setEntitiesScales(&entity, &scale, 1);
	}
}

void PropertyGrid::onGui()
{
	if (!m_is_opened) return;

	auto& ents = m_editor.getSelectedEntities();
	if (ImGui::Begin("Properties", &m_is_opened) && ents.size() == 1)
	{
		if (ImGui::Button("Add component"))
		{
			ImGui::OpenPopup("AddComponentPopup");
		}
		if (ImGui::BeginPopup("AddComponentPopup"))
		{
			for (int i = 0;
				i < m_editor.getEngine().getComponentTypesCount();
				++i)
			{
				if (ImGui::Selectable(
					m_editor.getEngine().getComponentTypeName(i)))
				{
					m_editor.addComponent(Lumix::crc32(
						m_editor.getEngine().getComponentTypeID(i)));
				}
			}
			ImGui::EndPopup();
		}

		showCoreProperties(ents[0]);

		auto& cmps = m_editor.getComponents(ents[0]);
		for (auto cmp : cmps)
		{
			showComponentProperties(cmp);
		}

	}
	ImGui::End();
}

<commit_msg>add/remove array item in property grid goes through the undo system<commit_after>#include "property_grid.h"
#include "asset_browser.h"
#include "core/crc32.h"
#include "editor/world_editor.h"
#include "engine/engine.h"
#include "engine/property_descriptor.h"
#include "ocornut-imgui/imgui.h"
#include "string_builder.h"
#include "terrain_editor.h"

const char* PropertyGrid::getComponentTypeName(Lumix::ComponentUID cmp) const
{
	auto& engine = m_editor.getEngine();
	for (int i = 0; i < engine.getComponentTypesCount(); ++i)
	{
		if (cmp.type ==
			Lumix::crc32(engine.getComponentTypeID(i)))
		{
			return engine.getComponentTypeName(i);
		}
	}
	return "Unknown";
}

PropertyGrid::PropertyGrid(Lumix::WorldEditor& editor, AssetBrowser& asset_browser)
	: m_is_opened(true)
	, m_editor(editor)
	, m_asset_browser(asset_browser)
{
	m_filter[0] = '\0';
	m_terrain_editor = editor.getAllocator().newObject<TerrainEditor>(editor);
}

PropertyGrid::~PropertyGrid()
{
	m_editor.getAllocator().deleteObject(m_terrain_editor);
}

bool PropertyGrid::getResourcePath(char* buf, int max_size, uint32_t resource_type)
{
	ImGui::InputText("Filter", m_filter, sizeof(m_filter));

	auto type = m_asset_browser.getTypeFromResourceManagerType(resource_type);
	for (auto unv : m_asset_browser.getResources(type))
	{
		if (m_filter[0] != '\0' && strstr(unv.c_str(), m_filter) == nullptr) continue;

		if (ImGui::Selectable(unv.c_str(), false))
		{
			Lumix::copyString(buf, max_size, unv.c_str());
			ImGui::EndPopup();
			return true;
		}
	}

	ImGui::EndPopup();
	return false;
}

void PropertyGrid::showProperty(Lumix::IPropertyDescriptor& desc, int index, Lumix::ComponentUID cmp)
{
	Lumix::OutputBlob stream(m_editor.getAllocator());
	if (index < 0)
		desc.get(cmp, stream);
	else
		desc.get(cmp, index, stream);
	Lumix::InputBlob tmp(stream);

	switch (desc.getType())
	{
	case Lumix::IPropertyDescriptor::DECIMAL:
	{
		float f;
		tmp.read(f);
		auto& d = static_cast<Lumix::IDecimalPropertyDescriptor&>(desc);
		if ((d.getMax() - d.getMin()) / d.getStep() <= 100)
		{
			if (ImGui::SliderFloat(desc.getName(), &f, d.getMin(), d.getMax()))
			{
				m_editor.setProperty(cmp.type, index, desc, &f, sizeof(f));
			}
		}
		else
		{
			if (ImGui::DragFloat(desc.getName(), &f, d.getStep(), d.getMin(), d.getMax()))
			{
				m_editor.setProperty(cmp.type, index, desc, &f, sizeof(f));
			}
		}
		break;
	}
	case Lumix::IPropertyDescriptor::INTEGER:
	{
		int i;
		tmp.read(i);
		if (ImGui::DragInt(desc.getName(), &i))
		{
			m_editor.setProperty(cmp.type, index, desc, &i, sizeof(i));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::BOOL:
	{
		bool b;
		tmp.read(b);
		if (ImGui::Checkbox(desc.getName(), &b))
		{
			m_editor.setProperty(cmp.type, index, desc, &b, sizeof(b));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::COLOR:
	{
		Lumix::Vec3 v;
		tmp.read(v);
		if (ImGui::ColorEdit3(desc.getName(), &v.x))
		{
			m_editor.setProperty(cmp.type, index, desc, &v, sizeof(v));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::VEC3:
	{
		Lumix::Vec3 v;
		tmp.read(v);
		if (ImGui::DragFloat3(desc.getName(), &v.x))
		{
			m_editor.setProperty(cmp.type, index, desc, &v, sizeof(v));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::VEC4:
	{
		Lumix::Vec4 v;
		tmp.read(v);
		if (ImGui::DragFloat4(desc.getName(), &v.x))
		{
			m_editor.setProperty(cmp.type, index, desc, &v, sizeof(v));
		}
		break;
	}
	case Lumix::IPropertyDescriptor::RESOURCE:
	{
		char buf[1024];
		Lumix::copyString(buf, sizeof(buf), (const char*)stream.getData());
		if (ImGui::InputText("", buf, sizeof(buf)))
		{
			m_editor.setProperty(cmp.type, index, desc, buf, strlen(buf) + 1);
		}
		ImGui::SameLine();
		if (ImGui::Button("Select"))
			ImGui::OpenPopup("SelectResourcePopup");
		if (ImGui::BeginPopup("SelectResourcePopup"))
		{
			auto& resource_descriptor = dynamic_cast<Lumix::ResourcePropertyDescriptorBase&>(desc);
			if (getResourcePath(buf, sizeof(buf), resource_descriptor.getResourceType()))
			{
				m_editor.setProperty(cmp.type, index, desc, buf, strlen(buf) + 1);
			}
		}
		break;
	}
	case Lumix::IPropertyDescriptor::STRING:
	case Lumix::IPropertyDescriptor::FILE:
	{
		char buf[1024];
		Lumix::copyString(buf, sizeof(buf), (const char*)stream.getData());
		if (ImGui::InputText(desc.getName(), buf, sizeof(buf)))
		{
			m_editor.setProperty(cmp.type, index, desc, buf, strlen(buf) + 1);
		}
		break;
	}
	case Lumix::IPropertyDescriptor::ARRAY:
		showArrayProperty(cmp, static_cast<Lumix::IArrayDescriptor&>(desc));
		break;
	default:
		ASSERT(false);
		break;
	}
}

void PropertyGrid::showArrayProperty(Lumix::ComponentUID cmp, Lumix::IArrayDescriptor& desc)
{
	if (!ImGui::CollapsingHeader(desc.getName(), nullptr, true, true)) return;

	int count = desc.getCount(cmp);
	if (ImGui::Button("Add"))
	{
		m_editor.addArrayPropertyItem(cmp, desc);
	}
	count = desc.getCount(cmp);

	for (int i = 0; i < count; ++i)
	{
		char tmp[10];
		Lumix::toCString(i, tmp, sizeof(tmp));
		if (ImGui::TreeNode(tmp))
		{
			ImGui::SameLine();
			if (ImGui::Button("Remove"))
			{
				m_editor.removeArrayPropertyItem(cmp, i, desc);
				--i;
				count = desc.getCount(cmp);
				ImGui::TreePop();
				continue;
			}

			for (int j = 0; j < desc.getChildren().size(); ++j)
			{
				auto* child = desc.getChildren()[j];
				showProperty(*child, i, cmp);
			}
			ImGui::TreePop();
		}
	}
}

void PropertyGrid::showComponentProperties(Lumix::ComponentUID cmp)
{
	if (!ImGui::CollapsingHeader(
		getComponentTypeName(cmp), nullptr, true, true))
		return;
	if (ImGui::Button(
		StringBuilder<30>("Remove component##", cmp.type)))
	{
		m_editor.destroyComponent(cmp);
		return;
	}

	auto& descs = m_editor.getEngine().getPropertyDescriptors(cmp.type);

	for (auto* desc : descs)
	{
		showProperty(*desc, -1, cmp);
	}

	if (cmp.type == Lumix::crc32("terrain"))
	{
		m_terrain_editor->setComponent(cmp);
		m_terrain_editor->onGui();
	}
}

void PropertyGrid::showCoreProperties(Lumix::Entity entity)
{
	char name[256];
	const char* tmp = m_editor.getUniverse()->getEntityName(entity);
	Lumix::copyString(name, sizeof(name), tmp);
	if (ImGui::InputText("Name", name, sizeof(name)))
	{
		m_editor.setEntityName(entity, name);
	}

	auto pos = m_editor.getUniverse()->getPosition(entity);
	if (ImGui::DragFloat3("Position", &pos.x))
	{
		m_editor.setEntitiesPositions(&entity, &pos, 1);
	}

	auto rot = m_editor.getUniverse()->getRotation(entity);
	if (ImGui::DragFloat4("Rotation", &rot.x))
	{
		m_editor.setEntitiesRotations(&entity, &rot, 1);
	}

	float scale = m_editor.getUniverse()->getScale(entity);
	if (ImGui::DragFloat("Scale", &scale, 0.1f))
	{
		m_editor.setEntitiesScales(&entity, &scale, 1);
	}
}

void PropertyGrid::onGui()
{
	if (!m_is_opened) return;

	auto& ents = m_editor.getSelectedEntities();
	if (ImGui::Begin("Properties", &m_is_opened) && ents.size() == 1)
	{
		if (ImGui::Button("Add component"))
		{
			ImGui::OpenPopup("AddComponentPopup");
		}
		if (ImGui::BeginPopup("AddComponentPopup"))
		{
			for (int i = 0;
				i < m_editor.getEngine().getComponentTypesCount();
				++i)
			{
				if (ImGui::Selectable(
					m_editor.getEngine().getComponentTypeName(i)))
				{
					m_editor.addComponent(Lumix::crc32(
						m_editor.getEngine().getComponentTypeID(i)));
				}
			}
			ImGui::EndPopup();
		}

		showCoreProperties(ents[0]);

		auto& cmps = m_editor.getComponents(ents[0]);
		for (auto cmp : cmps)
		{
			showComponentProperties(cmp);
		}

	}
	ImGui::End();
}

<|endoftext|>


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

#define base CSubsystem

// Implementation
CSkeletonSubsystem::CSkeletonSubsystem(const std::string &strName, core::log::Logger &logger)
    : base(strName, logger)
{
    // Provide mapping keys to upper layer
    addContextMappingKey("Owner");
    addContextMappingKey("Amend1");
    addContextMappingKey("Amend2");

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

// Implementation
CSkeletonSubsystem::CSkeletonSubsystem(const std::string &strName, core::log::Logger &logger)
    : CSubsystem(strName, logger)
{
    // Provide mapping keys to upper layer
    addContextMappingKey("Owner");
    addContextMappingKey("Amend1");
    addContextMappingKey("Amend2");

    // Provide creators to upper layer
    addSubsystemObjectFactory(
        new TSubsystemObjectFactory<CSkeletonSubsystemObject>("Message", 1 << ESkeletonOwner));
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "skia/ext/bitmap_platform_device_linux.h"

#include "skia/ext/bitmap_platform_device_data.h"

#include <cairo/cairo.h>

namespace skia {

namespace {

void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) {
  cairo_matrix_t cairo_matrix;
  cairo_matrix_init(&cairo_matrix,
                    SkScalarToFloat(matrix.getScaleX()),
                    SkScalarToFloat(matrix.getSkewY()),
                    SkScalarToFloat(matrix.getSkewX()),
                    SkScalarToFloat(matrix.getScaleY()),
                    SkScalarToFloat(matrix.getTranslateX()),
                    SkScalarToFloat(matrix.getTranslateY()));
  cairo_set_matrix(context, &cairo_matrix);
}

void LoadClipToContext(cairo_t* context, const SkRegion& clip) {
  cairo_reset_clip(context);

  // TODO(brettw) support non-rect clips.
  SkIRect bounding = clip.getBounds();
  cairo_rectangle(context, bounding.fLeft, bounding.fTop,
                  bounding.fRight - bounding.fLeft,
                  bounding.fBottom - bounding.fTop);
  cairo_clip(context);
}

}  // namespace

SkDevice* BitmapPlatformDeviceFactory::newDevice(SkBitmap::Config config,
                                                 int width, int height,
                                                 bool isOpaque,
                                                 bool isForLayer) {
  SkASSERT(config == SkBitmap::kARGB_8888_Config);
  return BitmapPlatformDevice::Create(width, height, isOpaque);
}

BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData(
    cairo_surface_t* surface)
    : surface_(surface),
      config_dirty_(true) {  // Want to load the config next time.
  bitmap_context_ = cairo_create(surface);
}

BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() {
  cairo_destroy(bitmap_context_);
  cairo_surface_destroy(surface_);
}

void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
    const SkMatrix& transform,
    const SkRegion& region) {
  transform_ = transform;
  clip_region_ = region;
  config_dirty_ = true;
}

void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() {
  if (!config_dirty_ || !bitmap_context_)
    return;  // Nothing to do.
  config_dirty_ = false;

  // Load the identity matrix since this is what our clip is relative to.
  cairo_matrix_t cairo_matrix;
  cairo_matrix_init_identity(&cairo_matrix);
  cairo_set_matrix(bitmap_context_, &cairo_matrix);

  LoadClipToContext(bitmap_context_, clip_region_);
  LoadMatrixToContext(bitmap_context_, transform_);
}

// We use this static factory function instead of the regular constructor so
// that we can create the pixel data before calling the constructor. This is
// required so that we can call the base class' constructor with the pixel
// data.
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
                                                   bool is_opaque,
                                                   cairo_surface_t* surface) {
  SkBitmap bitmap;
  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height,
                   cairo_image_surface_get_stride(surface));
  bitmap.setPixels(cairo_image_surface_get_data(surface));
  bitmap.setIsOpaque(is_opaque);

  // The device object will take ownership of the graphics context.
  return new BitmapPlatformDevice
      (bitmap, new BitmapPlatformDeviceData(surface));
}

BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
                                                   bool is_opaque) {
  cairo_surface_t* surface =
      cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                 width, height);

  BitmapPlatformDevice* device = Create(width, height, is_opaque, surface);

#ifndef NDEBUG
  if (is_opaque)  // Fill with bright bluish green
    device->eraseColor(SkColorSetARGB(255, 0, 255, 128));
#endif

  return device;
}

BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
                                                   bool is_opaque,
                                                   uint8_t* data) {
  cairo_surface_t* surface = cairo_image_surface_create_for_data(
      data, CAIRO_FORMAT_ARGB32, width, height,
      cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));

  return Create(width, height, is_opaque, surface);
}

// The device will own the bitmap, which corresponds to also owning the pixel
// data. Therefore, we do not transfer ownership to the SkDevice's bitmap.
BitmapPlatformDevice::BitmapPlatformDevice(
    const SkBitmap& bitmap,
    BitmapPlatformDeviceData* data)
    : PlatformDevice(bitmap),
      data_(data) {
}

BitmapPlatformDevice::BitmapPlatformDevice(
    const BitmapPlatformDevice& other)
    : PlatformDevice(const_cast<BitmapPlatformDevice&>(
                          other).accessBitmap(true)),
      data_(other.data_) {
}

BitmapPlatformDevice::~BitmapPlatformDevice() {
}

SkDeviceFactory* BitmapPlatformDevice::getDeviceFactory() {
  return SkNEW(BitmapPlatformDeviceFactory);
}

bool BitmapPlatformDevice::IsVectorial() {
  return false;
}

cairo_t* BitmapPlatformDevice::beginPlatformPaint() {
  data_->LoadConfig();
  cairo_t* cairo = data_->bitmap_context();
  // Tell Cairo that we've (probably) modified its pixel buffer without
  // its knowledge.
  cairo_surface_mark_dirty(cairo_get_target(cairo));
  return cairo;
}

void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
                                         const SkRegion& region) {
  data_->SetMatrixClip(transform, region);
}

BitmapPlatformDevice& BitmapPlatformDevice::operator=(
    const BitmapPlatformDevice& other) {
  data_ = other.data_;
  return *this;
}

}  // namespace skia
<commit_msg>Flush the cairo surface before we try to write to it.<commit_after>// Copyright (c) 2010 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 "skia/ext/bitmap_platform_device_linux.h"

#include "skia/ext/bitmap_platform_device_data.h"

#include <cairo/cairo.h>

namespace skia {

namespace {

void LoadMatrixToContext(cairo_t* context, const SkMatrix& matrix) {
  cairo_matrix_t cairo_matrix;
  cairo_matrix_init(&cairo_matrix,
                    SkScalarToFloat(matrix.getScaleX()),
                    SkScalarToFloat(matrix.getSkewY()),
                    SkScalarToFloat(matrix.getSkewX()),
                    SkScalarToFloat(matrix.getScaleY()),
                    SkScalarToFloat(matrix.getTranslateX()),
                    SkScalarToFloat(matrix.getTranslateY()));
  cairo_set_matrix(context, &cairo_matrix);
}

void LoadClipToContext(cairo_t* context, const SkRegion& clip) {
  cairo_reset_clip(context);

  // TODO(brettw) support non-rect clips.
  SkIRect bounding = clip.getBounds();
  cairo_rectangle(context, bounding.fLeft, bounding.fTop,
                  bounding.fRight - bounding.fLeft,
                  bounding.fBottom - bounding.fTop);
  cairo_clip(context);
}

}  // namespace

SkDevice* BitmapPlatformDeviceFactory::newDevice(SkBitmap::Config config,
                                                 int width, int height,
                                                 bool isOpaque,
                                                 bool isForLayer) {
  SkASSERT(config == SkBitmap::kARGB_8888_Config);
  return BitmapPlatformDevice::Create(width, height, isOpaque);
}

BitmapPlatformDevice::BitmapPlatformDeviceData::BitmapPlatformDeviceData(
    cairo_surface_t* surface)
    : surface_(surface),
      config_dirty_(true) {  // Want to load the config next time.
  bitmap_context_ = cairo_create(surface);
}

BitmapPlatformDevice::BitmapPlatformDeviceData::~BitmapPlatformDeviceData() {
  cairo_destroy(bitmap_context_);
  cairo_surface_destroy(surface_);
}

void BitmapPlatformDevice::BitmapPlatformDeviceData::SetMatrixClip(
    const SkMatrix& transform,
    const SkRegion& region) {
  transform_ = transform;
  clip_region_ = region;
  config_dirty_ = true;
}

void BitmapPlatformDevice::BitmapPlatformDeviceData::LoadConfig() {
  if (!config_dirty_ || !bitmap_context_)
    return;  // Nothing to do.
  config_dirty_ = false;

  // Load the identity matrix since this is what our clip is relative to.
  cairo_matrix_t cairo_matrix;
  cairo_matrix_init_identity(&cairo_matrix);
  cairo_set_matrix(bitmap_context_, &cairo_matrix);

  LoadClipToContext(bitmap_context_, clip_region_);
  LoadMatrixToContext(bitmap_context_, transform_);
}

// We use this static factory function instead of the regular constructor so
// that we can create the pixel data before calling the constructor. This is
// required so that we can call the base class' constructor with the pixel
// data.
BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
                                                   bool is_opaque,
                                                   cairo_surface_t* surface) {
  SkBitmap bitmap;
  bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height,
                   cairo_image_surface_get_stride(surface));
  bitmap.setPixels(cairo_image_surface_get_data(surface));
  bitmap.setIsOpaque(is_opaque);

  // The device object will take ownership of the graphics context.
  return new BitmapPlatformDevice
      (bitmap, new BitmapPlatformDeviceData(surface));
}

BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
                                                   bool is_opaque) {
  cairo_surface_t* surface =
      cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                 width, height);

  BitmapPlatformDevice* device = Create(width, height, is_opaque, surface);

#ifndef NDEBUG
  if (is_opaque)  // Fill with bright bluish green
    device->eraseColor(SkColorSetARGB(255, 0, 255, 128));
#endif

  return device;
}

BitmapPlatformDevice* BitmapPlatformDevice::Create(int width, int height,
                                                   bool is_opaque,
                                                   uint8_t* data) {
  cairo_surface_t* surface = cairo_image_surface_create_for_data(
      data, CAIRO_FORMAT_ARGB32, width, height,
      cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width));

  return Create(width, height, is_opaque, surface);
}

// The device will own the bitmap, which corresponds to also owning the pixel
// data. Therefore, we do not transfer ownership to the SkDevice's bitmap.
BitmapPlatformDevice::BitmapPlatformDevice(
    const SkBitmap& bitmap,
    BitmapPlatformDeviceData* data)
    : PlatformDevice(bitmap),
      data_(data) {
}

BitmapPlatformDevice::BitmapPlatformDevice(
    const BitmapPlatformDevice& other)
    : PlatformDevice(const_cast<BitmapPlatformDevice&>(
                          other).accessBitmap(true)),
      data_(other.data_) {
}

BitmapPlatformDevice::~BitmapPlatformDevice() {
}

SkDeviceFactory* BitmapPlatformDevice::getDeviceFactory() {
  return SkNEW(BitmapPlatformDeviceFactory);
}

bool BitmapPlatformDevice::IsVectorial() {
  return false;
}

cairo_t* BitmapPlatformDevice::beginPlatformPaint() {
  data_->LoadConfig();
  cairo_t* cairo = data_->bitmap_context();
  cairo_surface_t* surface = cairo_get_target(cairo);
  // Tell cairo to flush anything it has pending.
  cairo_surface_flush(surface);
  // Tell Cairo that we (probably) modified (actually, will modify) its pixel
  // buffer directly.
  cairo_surface_mark_dirty(surface);
  return cairo;
}

void BitmapPlatformDevice::setMatrixClip(const SkMatrix& transform,
                                         const SkRegion& region) {
  data_->SetMatrixClip(transform, region);
}

BitmapPlatformDevice& BitmapPlatformDevice::operator=(
    const BitmapPlatformDevice& other) {
  data_ = other.data_;
  return *this;
}

}  // namespace skia
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: attributemap.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: kz $ $Date: 2006-12-13 15:12:49 $
 *
 *  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_slideshow.hxx"

// must be first
#include <canvas/debug.hxx>
#include <canvas/canvastools.hxx>

#include "attributemap.hxx"
#include "tools.hxx"

namespace slideshow
{
    namespace internal
    {
        typedef ::canvas::tools::ValueMap< AttributeType > AnimateAttributeMap;

        AttributeType mapAttributeName( const ::rtl::OUString& rAttrName )
        {
            /** Maps attribute name to AttributeType enum.

                String entries are all case-insensitive and MUST
                BE STORED lowercase.

                String entries MUST BE SORTED in ascending order!
            */
            static AnimateAttributeMap::MapEntry lcl_attributeMap[] =
                {
                    { "charcolor", ATTRIBUTE_CHAR_COLOR },

                    { "charfontname", ATTRIBUTE_CHAR_FONT_NAME },

                    { "charheight", ATTRIBUTE_CHAR_HEIGHT },

                    { "charposture", ATTRIBUTE_CHAR_POSTURE },

                    // TODO(Q1): This should prolly be changed in PPT import
                    // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
                    { "charrotation", ATTRIBUTE_ROTATE },

                    { "charunderline", ATTRIBUTE_CHAR_UNDERLINE },

                    { "charweight", ATTRIBUTE_CHAR_WEIGHT },

                    { "color", ATTRIBUTE_COLOR },

                    { "dimcolor", ATTRIBUTE_DIMCOLOR },

                    { "fillcolor", ATTRIBUTE_FILL_COLOR },

                    { "fillstyle", ATTRIBUTE_FILL_STYLE },

                    { "height", ATTRIBUTE_HEIGHT },

                    { "linecolor", ATTRIBUTE_LINE_COLOR },

                    { "linestyle", ATTRIBUTE_LINE_STYLE },

                    { "opacity", ATTRIBUTE_OPACITY },

                    { "rotate", ATTRIBUTE_ROTATE },

                    { "skewx", ATTRIBUTE_SKEW_X },

                    { "skewy", ATTRIBUTE_SKEW_Y },

                    { "visibility", ATTRIBUTE_VISIBILITY },

                    { "width", ATTRIBUTE_WIDTH },

                    { "x", ATTRIBUTE_POS_X },

                    { "y", ATTRIBUTE_POS_Y }
                };

            static AnimateAttributeMap aMap( lcl_attributeMap,
                                             sizeof(lcl_attributeMap)/sizeof(*lcl_attributeMap),
                                             false );

            AttributeType eAttributeType = ATTRIBUTE_INVALID;

            // determine the type from the attribute name
            if( !aMap.lookup( rAttrName,
                              eAttributeType ) )
            {
                OSL_TRACE( "mapAttributeName(): attribute name %s not found in map.",
                           ::rtl::OUStringToOString( rAttrName,
                                                     RTL_TEXTENCODING_ASCII_US ).getStr() );
                return ATTRIBUTE_INVALID;
            }

            return eAttributeType;
        }

    }
}
<commit_msg>INTEGRATION: CWS changefileheader (1.7.74); FILE MERGED 2008/03/31 14:00:13 rt 1.7.74.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: attributemap.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

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

// must be first
#include <canvas/debug.hxx>
#include <canvas/canvastools.hxx>

#include "attributemap.hxx"
#include "tools.hxx"

namespace slideshow
{
    namespace internal
    {
        typedef ::canvas::tools::ValueMap< AttributeType > AnimateAttributeMap;

        AttributeType mapAttributeName( const ::rtl::OUString& rAttrName )
        {
            /** Maps attribute name to AttributeType enum.

                String entries are all case-insensitive and MUST
                BE STORED lowercase.

                String entries MUST BE SORTED in ascending order!
            */
            static AnimateAttributeMap::MapEntry lcl_attributeMap[] =
                {
                    { "charcolor", ATTRIBUTE_CHAR_COLOR },

                    { "charfontname", ATTRIBUTE_CHAR_FONT_NAME },

                    { "charheight", ATTRIBUTE_CHAR_HEIGHT },

                    { "charposture", ATTRIBUTE_CHAR_POSTURE },

                    // TODO(Q1): This should prolly be changed in PPT import
                    // { "charrotation", ATTRIBUTE_CHAR_ROTATION },
                    { "charrotation", ATTRIBUTE_ROTATE },

                    { "charunderline", ATTRIBUTE_CHAR_UNDERLINE },

                    { "charweight", ATTRIBUTE_CHAR_WEIGHT },

                    { "color", ATTRIBUTE_COLOR },

                    { "dimcolor", ATTRIBUTE_DIMCOLOR },

                    { "fillcolor", ATTRIBUTE_FILL_COLOR },

                    { "fillstyle", ATTRIBUTE_FILL_STYLE },

                    { "height", ATTRIBUTE_HEIGHT },

                    { "linecolor", ATTRIBUTE_LINE_COLOR },

                    { "linestyle", ATTRIBUTE_LINE_STYLE },

                    { "opacity", ATTRIBUTE_OPACITY },

                    { "rotate", ATTRIBUTE_ROTATE },

                    { "skewx", ATTRIBUTE_SKEW_X },

                    { "skewy", ATTRIBUTE_SKEW_Y },

                    { "visibility", ATTRIBUTE_VISIBILITY },

                    { "width", ATTRIBUTE_WIDTH },

                    { "x", ATTRIBUTE_POS_X },

                    { "y", ATTRIBUTE_POS_Y }
                };

            static AnimateAttributeMap aMap( lcl_attributeMap,
                                             sizeof(lcl_attributeMap)/sizeof(*lcl_attributeMap),
                                             false );

            AttributeType eAttributeType = ATTRIBUTE_INVALID;

            // determine the type from the attribute name
            if( !aMap.lookup( rAttrName,
                              eAttributeType ) )
            {
                OSL_TRACE( "mapAttributeName(): attribute name %s not found in map.",
                           ::rtl::OUStringToOString( rAttrName,
                                                     RTL_TEXTENCODING_ASCII_US ).getStr() );
                return ATTRIBUTE_INVALID;
            }

            return eAttributeType;
        }

    }
}
<|endoftext|>


<commit_before>#include "slic3r/Utils/Bonjour.hpp"   // On Windows, boost needs to be included before wxWidgets headers

#include "BonjourDialog.hpp"

#include <set>
#include <mutex>

#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/listctrl.h>
#include <wx/stattext.h>
#include <wx/timer.h>
#include <wx/wupdlock.h>

#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/Utils/Bonjour.hpp"

namespace Slic3r {

class BonjourReplyEvent : public wxEvent
{
public:
	BonjourReply reply;

	BonjourReplyEvent(wxEventType eventType, int winid, BonjourReply &&reply) :
		wxEvent(winid, eventType),
		reply(std::move(reply))
	{}

	virtual wxEvent *Clone() const
	{
		return new BonjourReplyEvent(*this);
	}
};

wxDEFINE_EVENT(EVT_BONJOUR_REPLY, BonjourReplyEvent);

wxDECLARE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent);
wxDEFINE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent);

class ReplySet: public std::set<BonjourReply> {};

struct LifetimeGuard
{
	std::mutex mutex;
	BonjourDialog *dialog;

	LifetimeGuard(BonjourDialog *dialog) : dialog(dialog) {}
};

BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
	: wxDialog(parent, wxID_ANY, _(L("Network lookup")), wxDefaultPosition, wxDefaultSize, wxRESIZE_BORDER)
	, list(new wxListView(this, wxID_ANY))
	, replies(new ReplySet)
	, label(new wxStaticText(this, wxID_ANY, ""))
	, timer(new wxTimer())
	, timer_state(0)
	, tech(tech)
{
	const int em = GUI::wxGetApp().em_unit();
	list->SetMinSize(wxSize(80 * em, 30 * em));

	wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);

	vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em);

	list->SetSingleStyle(wxLC_SINGLE_SEL);
	list->SetSingleStyle(wxLC_SORT_DESCENDING);
	list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 5 * em);
	list->AppendColumn(_(L("Hostname")), wxLIST_FORMAT_LEFT, 10 * em);
	list->AppendColumn(_(L("Service name")), wxLIST_FORMAT_LEFT, 20 * em);
	if (tech == ptFFF) {
		list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 5 * em);
	}

	vsizer->Add(list, 1, wxEXPAND | wxALL, em);

	wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
	button_sizer->Add(new wxButton(this, wxID_OK, "OK"), 0, wxALL, em);
	button_sizer->Add(new wxButton(this, wxID_CANCEL, "Cancel"), 0, wxALL, em);
	// ^ Note: The Ok/Cancel labels are translated by wxWidgets

	vsizer->Add(button_sizer, 0, wxALIGN_CENTER);
	SetSizerAndFit(vsizer);

	Bind(EVT_BONJOUR_REPLY, &BonjourDialog::on_reply, this);

	Bind(EVT_BONJOUR_COMPLETE, [this](wxCommandEvent &) {
		this->timer_state = 0;
	});

	Bind(wxEVT_TIMER, &BonjourDialog::on_timer, this);
}

BonjourDialog::~BonjourDialog()
{
	// Needed bacuse of forward defs
}

bool BonjourDialog::show_and_lookup()
{
	Show();   // Because we need GetId() to work before ShowModal()

	timer->Stop();
	timer->SetOwner(this);
	timer_state = 1;
	timer->Start(1000);
	wxTimerEvent evt_dummy;
	on_timer(evt_dummy);

	// The background thread needs to queue messages for this dialog
	// and for that it needs a valid pointer to it (mandated by the wxWidgets API).
	// Here we put the pointer under a shared_ptr and protect it by a mutex,
	// so that both threads can access it safely.
	auto dguard = std::make_shared<LifetimeGuard>(this);

	// Note: More can be done here when we support discovery of hosts other than Octoprint and SL1
	Bonjour::TxtKeys txt_keys { "version", "model" };

	bonjour = std::move(Bonjour("octoprint")
		.set_txt_keys(std::move(txt_keys))
		.set_retries(3)
		.set_timeout(4)
		.on_reply([dguard](BonjourReply &&reply) {
			std::lock_guard<std::mutex> lock_guard(dguard->mutex);
			auto dialog = dguard->dialog;
			if (dialog != nullptr) {
				auto evt = new BonjourReplyEvent(EVT_BONJOUR_REPLY, dialog->GetId(), std::move(reply));
				wxQueueEvent(dialog, evt);
			}
		})
		.on_complete([dguard]() {
			std::lock_guard<std::mutex> lock_guard(dguard->mutex);
			auto dialog = dguard->dialog;
			if (dialog != nullptr) {
				auto evt = new wxCommandEvent(EVT_BONJOUR_COMPLETE, dialog->GetId());
				wxQueueEvent(dialog, evt);
			}
		})
		.lookup()
	);

	bool res = ShowModal() == wxID_OK && list->GetFirstSelected() >= 0;
	{
		// Tell the background thread the dialog is going away...
		std::lock_guard<std::mutex> lock_guard(dguard->mutex);
		dguard->dialog = nullptr;
	}
	return res;
}

wxString BonjourDialog::get_selected() const
{
	auto sel = list->GetFirstSelected();
	return sel >= 0 ? list->GetItemText(sel) : wxString();
}

// Private

void BonjourDialog::on_reply(BonjourReplyEvent &e)
{
	if (replies->find(e.reply) != replies->end()) {
		// We already have this reply
		return;
	}

	// Filter replies based on selected technology
	const auto model = e.reply.txt_data.find("model");
	const bool sl1 = model != e.reply.txt_data.end() && model->second == "SL1";
	if (tech == ptFFF && sl1 || tech == ptSLA && !sl1) {
		return;
	}

	replies->insert(std::move(e.reply));

	auto selected = get_selected();

	wxWindowUpdateLocker freeze_guard(this);
	(void)freeze_guard;

	list->DeleteAllItems();

	// The whole list is recreated so that we benefit from it already being sorted in the set.
	// (And also because wxListView's sorting API is bananas.)
	for (const auto &reply : *replies) {
		auto item = list->InsertItem(0, reply.full_address);
		list->SetItem(item, 1, reply.hostname);
		list->SetItem(item, 2, reply.service_name);

		if (tech == ptFFF) {
			const auto it = reply.txt_data.find("version");
			if (it != reply.txt_data.end()) {
				list->SetItem(item, 3, GUI::from_u8(it->second));
			}
		}
	}

	const int em = GUI::wxGetApp().em_unit();

	for (int i = 0; i < list->GetColumnCount(); i++) {
		list->SetColumnWidth(i, wxLIST_AUTOSIZE);
		if (list->GetColumnWidth(i) < 10 * em) { list->SetColumnWidth(i, 10 * em); }
	}

	if (!selected.IsEmpty()) {
		// Attempt to preserve selection
		auto hit = list->FindItem(-1, selected);
		if (hit >= 0) { list->SetItemState(hit, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); }
	}
}

void BonjourDialog::on_timer(wxTimerEvent &)
{
	const auto search_str = _(L("Searching for devices"));

	if (timer_state > 0) {
		const std::string dots(timer_state, '.');
		label->SetLabel(wxString::Format("%s %s", search_str, dots));
		timer_state = (timer_state) % 3 + 1;
	} else {
		label->SetLabel(wxString::Format("%s: %s", search_str, _(L("Finished"))+"."));
		timer->Stop();
	}
}

}
<commit_msg>BonjourDialog: Fix dialog flags<commit_after>#include "slic3r/Utils/Bonjour.hpp"   // On Windows, boost needs to be included before wxWidgets headers

#include "BonjourDialog.hpp"

#include <set>
#include <mutex>

#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/listctrl.h>
#include <wx/stattext.h>
#include <wx/timer.h>
#include <wx/wupdlock.h>

#include "slic3r/GUI/GUI.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/I18N.hpp"
#include "slic3r/Utils/Bonjour.hpp"

namespace Slic3r {

class BonjourReplyEvent : public wxEvent
{
public:
	BonjourReply reply;

	BonjourReplyEvent(wxEventType eventType, int winid, BonjourReply &&reply) :
		wxEvent(winid, eventType),
		reply(std::move(reply))
	{}

	virtual wxEvent *Clone() const
	{
		return new BonjourReplyEvent(*this);
	}
};

wxDEFINE_EVENT(EVT_BONJOUR_REPLY, BonjourReplyEvent);

wxDECLARE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent);
wxDEFINE_EVENT(EVT_BONJOUR_COMPLETE, wxCommandEvent);

class ReplySet: public std::set<BonjourReply> {};

struct LifetimeGuard
{
	std::mutex mutex;
	BonjourDialog *dialog;

	LifetimeGuard(BonjourDialog *dialog) : dialog(dialog) {}
};

BonjourDialog::BonjourDialog(wxWindow *parent, Slic3r::PrinterTechnology tech)
	: wxDialog(parent, wxID_ANY, _(L("Network lookup")), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
	, list(new wxListView(this, wxID_ANY))
	, replies(new ReplySet)
	, label(new wxStaticText(this, wxID_ANY, ""))
	, timer(new wxTimer())
	, timer_state(0)
	, tech(tech)
{
	const int em = GUI::wxGetApp().em_unit();
	list->SetMinSize(wxSize(80 * em, 30 * em));

	wxBoxSizer *vsizer = new wxBoxSizer(wxVERTICAL);

	vsizer->Add(label, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, em);

	list->SetSingleStyle(wxLC_SINGLE_SEL);
	list->SetSingleStyle(wxLC_SORT_DESCENDING);
	list->AppendColumn(_(L("Address")), wxLIST_FORMAT_LEFT, 5 * em);
	list->AppendColumn(_(L("Hostname")), wxLIST_FORMAT_LEFT, 10 * em);
	list->AppendColumn(_(L("Service name")), wxLIST_FORMAT_LEFT, 20 * em);
	if (tech == ptFFF) {
		list->AppendColumn(_(L("OctoPrint version")), wxLIST_FORMAT_LEFT, 5 * em);
	}

	vsizer->Add(list, 1, wxEXPAND | wxALL, em);

	wxBoxSizer *button_sizer = new wxBoxSizer(wxHORIZONTAL);
	button_sizer->Add(new wxButton(this, wxID_OK, "OK"), 0, wxALL, em);
	button_sizer->Add(new wxButton(this, wxID_CANCEL, "Cancel"), 0, wxALL, em);
	// ^ Note: The Ok/Cancel labels are translated by wxWidgets

	vsizer->Add(button_sizer, 0, wxALIGN_CENTER);
	SetSizerAndFit(vsizer);

	Bind(EVT_BONJOUR_REPLY, &BonjourDialog::on_reply, this);

	Bind(EVT_BONJOUR_COMPLETE, [this](wxCommandEvent &) {
		this->timer_state = 0;
	});

	Bind(wxEVT_TIMER, &BonjourDialog::on_timer, this);
}

BonjourDialog::~BonjourDialog()
{
	// Needed bacuse of forward defs
}

bool BonjourDialog::show_and_lookup()
{
	Show();   // Because we need GetId() to work before ShowModal()

	timer->Stop();
	timer->SetOwner(this);
	timer_state = 1;
	timer->Start(1000);
	wxTimerEvent evt_dummy;
	on_timer(evt_dummy);

	// The background thread needs to queue messages for this dialog
	// and for that it needs a valid pointer to it (mandated by the wxWidgets API).
	// Here we put the pointer under a shared_ptr and protect it by a mutex,
	// so that both threads can access it safely.
	auto dguard = std::make_shared<LifetimeGuard>(this);

	// Note: More can be done here when we support discovery of hosts other than Octoprint and SL1
	Bonjour::TxtKeys txt_keys { "version", "model" };

	bonjour = std::move(Bonjour("octoprint")
		.set_txt_keys(std::move(txt_keys))
		.set_retries(3)
		.set_timeout(4)
		.on_reply([dguard](BonjourReply &&reply) {
			std::lock_guard<std::mutex> lock_guard(dguard->mutex);
			auto dialog = dguard->dialog;
			if (dialog != nullptr) {
				auto evt = new BonjourReplyEvent(EVT_BONJOUR_REPLY, dialog->GetId(), std::move(reply));
				wxQueueEvent(dialog, evt);
			}
		})
		.on_complete([dguard]() {
			std::lock_guard<std::mutex> lock_guard(dguard->mutex);
			auto dialog = dguard->dialog;
			if (dialog != nullptr) {
				auto evt = new wxCommandEvent(EVT_BONJOUR_COMPLETE, dialog->GetId());
				wxQueueEvent(dialog, evt);
			}
		})
		.lookup()
	);

	bool res = ShowModal() == wxID_OK && list->GetFirstSelected() >= 0;
	{
		// Tell the background thread the dialog is going away...
		std::lock_guard<std::mutex> lock_guard(dguard->mutex);
		dguard->dialog = nullptr;
	}
	return res;
}

wxString BonjourDialog::get_selected() const
{
	auto sel = list->GetFirstSelected();
	return sel >= 0 ? list->GetItemText(sel) : wxString();
}

// Private

void BonjourDialog::on_reply(BonjourReplyEvent &e)
{
	if (replies->find(e.reply) != replies->end()) {
		// We already have this reply
		return;
	}

	// Filter replies based on selected technology
	const auto model = e.reply.txt_data.find("model");
	const bool sl1 = model != e.reply.txt_data.end() && model->second == "SL1";
	if (tech == ptFFF && sl1 || tech == ptSLA && !sl1) {
		return;
	}

	replies->insert(std::move(e.reply));

	auto selected = get_selected();

	wxWindowUpdateLocker freeze_guard(this);
	(void)freeze_guard;

	list->DeleteAllItems();

	// The whole list is recreated so that we benefit from it already being sorted in the set.
	// (And also because wxListView's sorting API is bananas.)
	for (const auto &reply : *replies) {
		auto item = list->InsertItem(0, reply.full_address);
		list->SetItem(item, 1, reply.hostname);
		list->SetItem(item, 2, reply.service_name);

		if (tech == ptFFF) {
			const auto it = reply.txt_data.find("version");
			if (it != reply.txt_data.end()) {
				list->SetItem(item, 3, GUI::from_u8(it->second));
			}
		}
	}

	const int em = GUI::wxGetApp().em_unit();

	for (int i = 0; i < list->GetColumnCount(); i++) {
		list->SetColumnWidth(i, wxLIST_AUTOSIZE);
		if (list->GetColumnWidth(i) < 10 * em) { list->SetColumnWidth(i, 10 * em); }
	}

	if (!selected.IsEmpty()) {
		// Attempt to preserve selection
		auto hit = list->FindItem(-1, selected);
		if (hit >= 0) { list->SetItemState(hit, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED); }
	}
}

void BonjourDialog::on_timer(wxTimerEvent &)
{
	const auto search_str = _(L("Searching for devices"));

	if (timer_state > 0) {
		const std::string dots(timer_state, '.');
		label->SetLabel(wxString::Format("%s %s", search_str, dots));
		timer_state = (timer_state) % 3 + 1;
	} else {
		label->SetLabel(wxString::Format("%s: %s", search_str, _(L("Finished"))+"."));
		timer->Stop();
	}
}

}
<|endoftext|>


<commit_before>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <algebra/NDSS.h>
#include <thread>
#include <atomic>
#include <vector>

#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREAD

std::vector<MDL::EncVector>encrypt(const MDL::Matrix<long>& data,
                                   const FHEPubKey        & pk,
                                   const EncryptedArray   & ea,
                                   long                     rows_to_proces = 0)
{
    MDL::Timer timer;
    std::vector<MDL::EncVector> ctxts(data.rows(), pk);
    std::vector<std::thread>    workers;
    std::atomic<size_t> counter(0);

    rows_to_proces = rows_to_proces == 0 ? data.rows() : rows_to_proces;
    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&data, &ea, &rows_to_proces,
                                                 &counter, &ctxts]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < rows_to_proces) {
                ctxts[next].pack(data[next], ea);
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    timer.end();
    printf("Encrypt %ld data with %ld workers costed %f sec\n", rows_to_proces,
           WORKER_NR, timer.second());
    return ctxts;
}

MDL::EncVector mean(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) {
        wr.join();
    }

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Mean %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

MDL::EncVector variance(std::vector<MDL::EncVector>& ctxts)
{
    MDL::Timer timer;
    NTL::ZZX   N(ctxts.size());
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    timer.start();
    WORKER_NR = 1;
    auto sum_sq = mean(ctxts);
    sum_sq.square();
    MDL::Timer mult_timer;
    mult_timer.start();
    WORKER_NR = 8;

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&ctxts, &counter]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ctxts[next].square();
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    mult_timer.end();
    printf("Square costed %f sec\n", mult_timer.second());
    WORKER_NR = 1;
    auto sq_sum = mean(ctxts);
    WORKER_NR = 8;
    sq_sum.multByConstant(N);
    sq_sum.addCtxt(sum_sq, true);
    timer.end();
    printf("Variance %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return sq_sum;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data   = load_csv("adult.data", 100);
    auto result = load_csv("adult_result");
    auto ctxts  = encrypt(data, pk, ea);

    // {
    //     MDL::Vector<long> ret;
    //     auto summaiton = mean(ctxts);
    //     summaiton.unpack(ret, sk, ea);
    //     std::cout << ret << std::endl;
    //     std::cout << result[0] << std::endl;
    // }

    {
        MDL::Vector<long> ret;

        auto var = variance(ctxts);
        var.unpack(ret, sk, ea);
        std::cout << ret << std::endl;
        std::cout << result[1] << std::endl;
    }
    return 0;
}
<commit_msg>One core version variance<commit_after>#include <fhe/FHEContext.h>
#include <fhe/FHE.h>
#include <fhe/NumbTh.h>
#include <fhe/EncryptedArray.h>
#include <utils/FileUtils.hpp>
#include <utils/timer.hpp>
#include <algebra/NDSS.h>
#include <thread>
#include <atomic>
#include <vector>

#ifdef FHE_THREADS
long WORKER_NR = 8;
#else // ifdef FHE_THREADS
long WORKER_NR = 1;
#endif // ifdef FHE_THREAD

MDL::EncVector encrypt_variance(const MDL::Matrix<long>& data,
                                const FHEPubKey        & pk,
                                const EncryptedArray   & ea)
{
    MDL::EncVector sq_sum(pk), sum_sq(pk);
    MDL::EncVector encRow(pk);
    NTL::ZZX N(data.rows());
    MDL::Timer timer;

    timer.start();

    for (size_t row = 0; row < data.rows(); row++) {
        encRow.pack(data[row], ea);

        if (row == 0) {
            sum_sq = encRow;
            encRow.square();
            sq_sum = encRow;
        } else {
            sum_sq += encRow;
            encRow.square();
            sq_sum += encRow;
        }
    }
    sq_sum.multByConstant(N);
    sq_sum -= sum_sq;
    timer.end();
    printf("Encrypt & Variance of %ld records costed %fs\n", data.rows(),
           timer.second());
    return sq_sum;
}

std::vector<MDL::EncVector>encrypt(const MDL::Matrix<long>& data,
                                   const FHEPubKey        & pk,
                                   const EncryptedArray   & ea,
                                   long                     rows_to_proces = 0)
{
    MDL::Timer timer;
    std::vector<MDL::EncVector> ctxts(data.rows(), pk);
    std::vector<std::thread>    workers;
    std::atomic<size_t> counter(0);

    rows_to_proces = rows_to_proces == 0 ? data.rows() : rows_to_proces;
    timer.start();

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&data, &ea, &rows_to_proces,
                                                 &counter, &ctxts]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < rows_to_proces) {
                ctxts[next].pack(data[next], ea);
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    timer.end();
    printf("Encrypt %ld data with %ld workers costed %f sec\n", rows_to_proces,
           WORKER_NR, timer.second());
    return ctxts;
}

MDL::EncVector mean(const std::vector<MDL::EncVector>& ctxts)
{
    std::vector<std::thread>    workers;
    std::vector<MDL::EncVector> partials(WORKER_NR, ctxts[0].getPubKey());
    std::atomic<size_t> counter(WORKER_NR);
    MDL::Timer timer;

    timer.start();

    for (long i = 0; i < WORKER_NR; i++) {
        partials[i] = ctxts[i];
        workers.push_back(std::move(std::thread([&counter, &ctxts]
                                                    (MDL::EncVector& ct) {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ct += ctxts[next];
            }
        }, std::ref(partials[i]))));
    }

    for (auto && wr : workers) {
        wr.join();
    }

    for (long i = 1; i < WORKER_NR; i++) {
        partials[0] += partials[i];
    }
    timer.end();
    printf("Mean %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return partials[0];
}

MDL::EncVector variance(std::vector<MDL::EncVector>& ctxts)
{
    MDL::Timer timer;
    NTL::ZZX   N(ctxts.size());
    std::atomic<size_t> counter(0);
    std::vector<std::thread> workers;

    timer.start();
    WORKER_NR = 1;
    auto sum_sq = mean(ctxts);
    sum_sq.square();
    MDL::Timer mult_timer;
    mult_timer.start();
    WORKER_NR = 8;

    for (long wr = 0; wr < WORKER_NR; wr++) {
        workers.push_back(std::move(std::thread([&ctxts, &counter]() {
            size_t next;

            while ((next = counter.fetch_add(1)) < ctxts.size()) {
                ctxts[next].square();
            }
        })));
    }

    for (auto && wr : workers) wr.join();
    mult_timer.end();
    printf("Square costed %f sec\n", mult_timer.second());
    WORKER_NR = 1;
    auto sq_sum = mean(ctxts);
    WORKER_NR = 8;
    sq_sum.multByConstant(N);
    sq_sum.addCtxt(sum_sq, true);
    timer.end();
    printf("Variance %zd data with %ld workers costed %f sec\n", ctxts.size(),
           WORKER_NR, timer.second());
    return sq_sum;
}

int main(int argc, char *argv[]) {
    long m, p, r, L;
    ArgMapping argmap;

    argmap.arg("m", m, "m");
    argmap.arg("L", L, "L");
    argmap.arg("p", p, "p");
    argmap.arg("r", r, "r");
    argmap.parse(argc, argv);

    FHEcontext context(m, p, r);
    buildModChain(context, L);
    FHESecKey sk(context);
    sk.GenSecKey(64);
    addSome1DMatrices(sk);
    FHEPubKey pk = sk;

    auto G = context.alMod.getFactorsOverZZ()[0];
    EncryptedArray ea(context, G);

    auto data   = load_csv("adult.data", 100);
    auto result = load_csv("adult_result");

    // auto ctxts  = encrypt(data, pk, ea);

    // {
    //     MDL::Vector<long> ret;
    //     auto summaiton = mean(ctxts);
    //     summaiton.unpack(ret, sk, ea);
    //     std::cout << ret << std::endl;
    //     std::cout << result[0] << std::endl;
    // }

    {
        MDL::Vector<long> ret;

        auto var = encrypt_variance(data, pk, ea);
        var.unpack(ret, sk, ea);
        std::cout << ret << std::endl;
        std::cout << result[1] << std::endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>//
// Copyright Copyright 2009-2019, AMT – The Association For Manufacturing Technology (“AMT”)
// All rights reserved.
//
//    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 <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <nlohmann/json.hpp>

#include "component_event.hpp"
#include "data_item.hpp"
#include "device.hpp"
#include "json_printer.hpp"
#include "globals.hpp"
#include "checkpoint.hpp"
#include "xml_parser.hpp"
#include "xml_printer.hpp"
#include "test_globals.hpp"

using json = nlohmann::json;
using namespace std;

namespace mtconnect {
  namespace test {
    class JsonPrinterProbeTest : public CppUnit::TestFixture
    {
      CPPUNIT_TEST_SUITE(JsonPrinterProbeTest);
      CPPUNIT_TEST(testDeviceRootAndDescription);
      CPPUNIT_TEST(testTopLevelDataItems);
      CPPUNIT_TEST(testSubComponents);
      CPPUNIT_TEST_SUITE_END();

    public:
      void testDeviceRootAndDescription();
      void testTopLevelDataItems();
      void testSubComponents();

      void setUp();
      void tearDown();

    protected:
      std::unique_ptr<JsonPrinter> m_printer;
      std::vector<Device *> m_devices;

      std::unique_ptr<XmlParser> m_config;
      std::unique_ptr<XmlPrinter> m_xmlPrinter;
    };

    CPPUNIT_TEST_SUITE_REGISTRATION(JsonPrinterProbeTest);

    void JsonPrinterProbeTest::setUp()
    {
      m_xmlPrinter.reset(new XmlPrinter("1.5"));
      m_printer.reset(new JsonPrinter("1.5", true));

      m_config.reset(new XmlParser());
      m_devices = m_config->parseFile("../samples/test_config.xml", m_xmlPrinter.get());
    }

    void JsonPrinterProbeTest::tearDown()
    {
      m_config.reset();
      m_xmlPrinter.reset();
      m_printer.reset();
      m_devices.clear();
    }

    void JsonPrinterProbeTest::testDeviceRootAndDescription()
    {
      auto doc = m_printer->printProbe(123, 9999, 1, 1024, 10, m_devices);
      auto jdoc = json::parse(doc);
      auto it = jdoc.begin();
      CPPUNIT_ASSERT_EQUAL(string("MTConnectDevices"), it.key());
      CPPUNIT_ASSERT_EQUAL(123, jdoc.at("/MTConnectDevices/Header/@instanceId"_json_pointer).get<int32_t>());
      CPPUNIT_ASSERT_EQUAL(9999, jdoc.at("/MTConnectDevices/Header/@bufferSize"_json_pointer).get<int32_t>());
      CPPUNIT_ASSERT_EQUAL(1024, jdoc.at("/MTConnectDevices/Header/@assetBufferSize"_json_pointer).get<int32_t>());
      CPPUNIT_ASSERT_EQUAL(10, jdoc.at("/MTConnectDevices/Header/@assetCount"_json_pointer).get<int32_t>());

      auto devices = jdoc.at("/MTConnectDevices/Devices"_json_pointer);
      auto device = devices.at(0).at("/Device"_json_pointer);

      CPPUNIT_ASSERT_EQUAL(string("d"), device.at("/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("LinuxCNC"), device.at("/@name"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("000"), device.at("/@uuid"_json_pointer).get<string>());

      CPPUNIT_ASSERT_EQUAL(string("Linux CNC Device"), device.at("/Description/#text"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("NIST"), device.at("/Description/@manufacturer"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("1122"), device.at("/Description/@serialNumber"_json_pointer).get<string>());
    }

    void JsonPrinterProbeTest::testTopLevelDataItems()
    {
      auto doc = m_printer->printProbe(123, 9999, 1, 1024, 10, m_devices);
      //cout << "\n" << doc << endl;
      auto jdoc = json::parse(doc);
      auto devices = jdoc.at("/MTConnectDevices/Devices"_json_pointer);
      auto device = devices.at(0).at("/Device"_json_pointer);

      auto dataItems = device.at("/DataItems"_json_pointer);
      CPPUNIT_ASSERT(dataItems.is_array());
      CPPUNIT_ASSERT_EQUAL(2ul, static_cast<unsigned long>(dataItems.size()));

      // Alarm event
      auto alarm = dataItems.at(0);
      CPPUNIT_ASSERT_EQUAL(string("ALARM"), alarm.at("/DataItem/@type"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("EVENT"), alarm.at("/DataItem/@category"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("a"), alarm.at("/DataItem/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("alarm"), alarm.at("/DataItem/@name"_json_pointer).get<string>());

      // Availability event
      auto avail = dataItems.at(1);
      CPPUNIT_ASSERT_EQUAL(string("AVAILABILITY"), avail.at("/DataItem/@type"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("EVENT"), avail.at("/DataItem/@category"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("avail"), avail.at("/DataItem/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("avail"), avail.at("/DataItem/@name"_json_pointer).get<string>());

    }

    void JsonPrinterProbeTest::testSubComponents()
    {
      auto doc = m_printer->printProbe(123, 9999, 1, 1024, 10, m_devices);
      cout << "\n" << doc << endl;
      auto jdoc = json::parse(doc);
      auto devices = jdoc.at("/MTConnectDevices/Devices"_json_pointer);
      auto device = devices.at(0).at("/Device"_json_pointer);

      auto components = device.at("/Components"_json_pointer);
      CPPUNIT_ASSERT(components.is_array());
      CPPUNIT_ASSERT_EQUAL(3ul, static_cast<unsigned long>(components.size()));

      auto axes = components.at(0);
      CPPUNIT_ASSERT(axes.is_object());
      CPPUNIT_ASSERT_EQUAL(string("Axes"), axes.begin().key());
      CPPUNIT_ASSERT_EQUAL(string("axes"), axes.at("/Axes/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("Axes"), axes.at("/Axes/@name"_json_pointer).get<string>());

      auto subAxes = axes.at("/Axes/Components"_json_pointer);
      CPPUNIT_ASSERT(subAxes.is_array());
      CPPUNIT_ASSERT_EQUAL(4ul, static_cast<unsigned long>(subAxes.size()));

      auto rotary = subAxes.at(0);
      CPPUNIT_ASSERT(rotary.is_object());
      auto rc = rotary.at("/Rotary"_json_pointer);
      CPPUNIT_ASSERT(rc.is_object());
      CPPUNIT_ASSERT_EQUAL(string("C"), rc.at("/@name"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("c"), rc.at("/@id"_json_pointer).get<string>());

      auto dataItems = rc.at("/DataItems"_json_pointer);
      CPPUNIT_ASSERT(dataItems.is_array());

      auto ss = dataItems.at(0).at("/DataItem"_json_pointer);
      CPPUNIT_ASSERT(ss.is_object());
      CPPUNIT_ASSERT_EQUAL(string("SPINDLE_SPEED"), ss.at("/@type"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("REVOLUTION/MINUTE"), ss.at("/@units"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("REVOLUTION/MINUTE"), ss.at("/@nativeUnits"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("ACTUAL"), ss.at("/@subType"_json_pointer).get<string>());

      auto source = ss.at("/Source"_json_pointer);
      CPPUNIT_ASSERT(source.is_object());

      CPPUNIT_ASSERT_EQUAL(string("spindle_speed"), ss.at("/Source/#text"_json_pointer).get<string>());

    }

  }
}

<commit_msg>Cleaned up size literal casting. Use constexpr to do conversion and _S for size_type cast.<commit_after>//
// Copyright Copyright 2009-2019, AMT – The Association For Manufacturing Technology (“AMT”)
// All rights reserved.
//
//    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 <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <nlohmann/json.hpp>

#include "component_event.hpp"
#include "data_item.hpp"
#include "device.hpp"
#include "json_printer.hpp"
#include "globals.hpp"
#include "checkpoint.hpp"
#include "xml_parser.hpp"
#include "xml_printer.hpp"
#include "test_globals.hpp"

using json = nlohmann::json;
using namespace std;

namespace mtconnect {
  namespace test {
    constexpr nlohmann::json::size_type operator "" _S(unsigned long long v)
    {
      return static_cast<nlohmann::json::size_type>(v);
    }

    class JsonPrinterProbeTest : public CppUnit::TestFixture
    {
      CPPUNIT_TEST_SUITE(JsonPrinterProbeTest);
      CPPUNIT_TEST(testDeviceRootAndDescription);
      CPPUNIT_TEST(testTopLevelDataItems);
      CPPUNIT_TEST(testSubComponents);
      CPPUNIT_TEST_SUITE_END();

    public:
      void testDeviceRootAndDescription();
      void testTopLevelDataItems();
      void testSubComponents();

      void setUp();
      void tearDown();

    protected:
      std::unique_ptr<JsonPrinter> m_printer;
      std::vector<Device *> m_devices;

      std::unique_ptr<XmlParser> m_config;
      std::unique_ptr<XmlPrinter> m_xmlPrinter;
    };

    CPPUNIT_TEST_SUITE_REGISTRATION(JsonPrinterProbeTest);

    void JsonPrinterProbeTest::setUp()
    {
      m_xmlPrinter.reset(new XmlPrinter("1.5"));
      m_printer.reset(new JsonPrinter("1.5", true));

      m_config.reset(new XmlParser());
      m_devices = m_config->parseFile("../samples/test_config.xml", m_xmlPrinter.get());
    }

    void JsonPrinterProbeTest::tearDown()
    {
      m_config.reset();
      m_xmlPrinter.reset();
      m_printer.reset();
      m_devices.clear();
    }

    void JsonPrinterProbeTest::testDeviceRootAndDescription()
    {
      auto doc = m_printer->printProbe(123, 9999, 1, 1024, 10, m_devices);
      auto jdoc = json::parse(doc);
      auto it = jdoc.begin();
      CPPUNIT_ASSERT_EQUAL(string("MTConnectDevices"), it.key());
      CPPUNIT_ASSERT_EQUAL(123, jdoc.at("/MTConnectDevices/Header/@instanceId"_json_pointer).get<int32_t>());
      CPPUNIT_ASSERT_EQUAL(9999, jdoc.at("/MTConnectDevices/Header/@bufferSize"_json_pointer).get<int32_t>());
      CPPUNIT_ASSERT_EQUAL(1024, jdoc.at("/MTConnectDevices/Header/@assetBufferSize"_json_pointer).get<int32_t>());
      CPPUNIT_ASSERT_EQUAL(10, jdoc.at("/MTConnectDevices/Header/@assetCount"_json_pointer).get<int32_t>());

      auto devices = jdoc.at("/MTConnectDevices/Devices"_json_pointer);
      auto device = devices.at(0).at("/Device"_json_pointer);

      CPPUNIT_ASSERT_EQUAL(string("d"), device.at("/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("LinuxCNC"), device.at("/@name"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("000"), device.at("/@uuid"_json_pointer).get<string>());

      CPPUNIT_ASSERT_EQUAL(string("Linux CNC Device"), device.at("/Description/#text"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("NIST"), device.at("/Description/@manufacturer"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("1122"), device.at("/Description/@serialNumber"_json_pointer).get<string>());
    }

    void JsonPrinterProbeTest::testTopLevelDataItems()
    {
      auto doc = m_printer->printProbe(123, 9999, 1, 1024, 10, m_devices);
      //cout << "\n" << doc << endl;
      auto jdoc = json::parse(doc);
      auto devices = jdoc.at("/MTConnectDevices/Devices"_json_pointer);
      auto device = devices.at(0).at("/Device"_json_pointer);

      auto dataItems = device.at("/DataItems"_json_pointer);
      CPPUNIT_ASSERT(dataItems.is_array());
      CPPUNIT_ASSERT_EQUAL(2_S, dataItems.size());

      // Alarm event
      auto alarm = dataItems.at(0);
      CPPUNIT_ASSERT_EQUAL(string("ALARM"), alarm.at("/DataItem/@type"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("EVENT"), alarm.at("/DataItem/@category"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("a"), alarm.at("/DataItem/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("alarm"), alarm.at("/DataItem/@name"_json_pointer).get<string>());

      // Availability event
      auto avail = dataItems.at(1);
      CPPUNIT_ASSERT_EQUAL(string("AVAILABILITY"), avail.at("/DataItem/@type"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("EVENT"), avail.at("/DataItem/@category"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("avail"), avail.at("/DataItem/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("avail"), avail.at("/DataItem/@name"_json_pointer).get<string>());

    }

    void JsonPrinterProbeTest::testSubComponents()
    {
      auto doc = m_printer->printProbe(123, 9999, 1, 1024, 10, m_devices);
      cout << "\n" << doc << endl;
      auto jdoc = json::parse(doc);
      auto devices = jdoc.at("/MTConnectDevices/Devices"_json_pointer);
      auto device = devices.at(0).at("/Device"_json_pointer);

      auto components = device.at("/Components"_json_pointer);
      CPPUNIT_ASSERT(components.is_array());
      CPPUNIT_ASSERT_EQUAL(3_S, components.size());

      auto axes = components.at(0);
      CPPUNIT_ASSERT(axes.is_object());
      CPPUNIT_ASSERT_EQUAL(string("Axes"), axes.begin().key());
      CPPUNIT_ASSERT_EQUAL(string("axes"), axes.at("/Axes/@id"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("Axes"), axes.at("/Axes/@name"_json_pointer).get<string>());

      auto subAxes = axes.at("/Axes/Components"_json_pointer);
      CPPUNIT_ASSERT(subAxes.is_array());
      CPPUNIT_ASSERT_EQUAL(4_S, subAxes.size());

      auto rotary = subAxes.at(0);
      CPPUNIT_ASSERT(rotary.is_object());
      auto rc = rotary.at("/Rotary"_json_pointer);
      CPPUNIT_ASSERT(rc.is_object());
      CPPUNIT_ASSERT_EQUAL(string("C"), rc.at("/@name"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("c"), rc.at("/@id"_json_pointer).get<string>());

      auto dataItems = rc.at("/DataItems"_json_pointer);
      CPPUNIT_ASSERT(dataItems.is_array());

      auto ss = dataItems.at(0).at("/DataItem"_json_pointer);
      CPPUNIT_ASSERT(ss.is_object());
      CPPUNIT_ASSERT_EQUAL(string("SPINDLE_SPEED"), ss.at("/@type"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("REVOLUTION/MINUTE"), ss.at("/@units"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("REVOLUTION/MINUTE"), ss.at("/@nativeUnits"_json_pointer).get<string>());
      CPPUNIT_ASSERT_EQUAL(string("ACTUAL"), ss.at("/@subType"_json_pointer).get<string>());

      auto source = ss.at("/Source"_json_pointer);
      CPPUNIT_ASSERT(source.is_object());

      CPPUNIT_ASSERT_EQUAL(string("spindle_speed"), ss.at("/Source/#text"_json_pointer).get<string>());

    }

  }
}

<|endoftext|>