<commit_before>#include "InterpolationFunction.h"
#include <QtGlobal>
#include <math.h>
#include <QtCore/QStringList>
#include "Workspace.h"
#include "SimulatedAnnealing.h"
#include <set>
#include <limits>
#include <boost/foreach.hpp>

//Optimierer: min_a (A*a - y)
extern "C"{
	int sgels_(char *trans, int *m, int *n, int * nrhs,
		float *a, int *lda, float *b, int *ldb, float *work,
		int *lwork, int *info);

	int dgels_(char *trans, int *m, int *n, int * nrhs,
		double *a, int *lda, double *b, int *ldb,
		double *work, int *lwork, int *info);
}

InterpolationFunction::InterpolationFunction(QString pjob_file, QString result)
: m_pjob_file(pjob_file), m_result(result), m_mu(0.5), m_d(0)
{
	buildParameterSorting();
	m_interpolationPoints = interpolationPoints();
	m_interpolationValues = interpolationValues();
	Q_ASSERT(m_interpolationPoints.size() == m_interpolationValues.size());
	remove_infs_and_nans(m_interpolationPoints, m_interpolationValues);
	Q_ASSERT(m_interpolationPoints.size() == m_interpolationValues.size());
	BOOST_FOREACH(std::vector<double>& point, m_interpolationPoints){
		Q_ASSERT(point.size() == m_interpolationPoints[0].size());
	}

	m_xarr = new double[m_interpolationPoints[0].size()];

	calculateMeanDistance();
	calculateAlphas(m_interpolationPoints,m_interpolationValues);
}

void InterpolationFunction::buildParameterSorting(){
	QSet< QHash<QString,double> > parameterCombinations = Workspace::getInstace().getResults().parameterCombinationsFor(m_pjob_file);
	QSet< QString > parameterNames;
	QHash<QString,double> combination;
	foreach(combination, parameterCombinations){
		QString parameterName;
		foreach(parameterName, combination.keys())
			parameterNames.insert(parameterName);
	}
	QStringList sortedParameterNames = parameterNames.toList();
	qSort(sortedParameterNames);
	for(int i=0;i<sortedParameterNames.size();++i)
		m_parameterSorting[sortedParameterNames.at(i)] = i;
}

vector< vector<double> > InterpolationFunction::interpolationPoints(){
	vector< vector<double> > result;
	QSet< QHash<QString,double> > parameterCombinations = Workspace::getInstace().getResults().parameterCombinationsFor(m_pjob_file);
	QHash<QString,double> combination;
	foreach(combination, parameterCombinations){
		QString parameterName;
		vector<double> parameterValues;
		parameterValues.resize(combination.size());
		foreach(parameterName, combination.keys())
			parameterValues[m_parameterSorting[parameterName]] = combination[parameterName];
		result.push_back(parameterValues);
	}
	return result;
}

vector<double> InterpolationFunction::interpolationValues(){
	vector<double> result;
	QSet< QHash<QString,double> > parameterCombinations = Workspace::getInstace().getResults().parameterCombinationsFor(m_pjob_file);
	QHash<QString,double> combination;
	foreach(combination, parameterCombinations){
		result.push_back(Workspace::getInstace().getResults().getValue(m_pjob_file,m_result,combination));
	}
	return result;
}

InterpolationFunction::~InterpolationFunction(){
	delete[] m_xarr;
}

double InterpolationFunction::getValue(QHash< QString, double > parameters){
	if(m_interpolationPoints.size() == 0) return 0;
    Q_ASSERT(parameters.size() == static_cast<int>(m_interpolationPoints[0].size()));
	QString parameterName;
	foreach(parameterName, parameters.keys())
	m_xarr[m_parameterSorting[parameterName]] = parameters[parameterName];

	return f(m_xarr);
}

double InterpolationFunction::f(double* x){
	//if(!m_hasSolution) return 0;

		double sum=0;
//		//x skalieren:
//		Data* main = Schlangensicht::getInstance().getMainData();
//		for(unsigned int i=0; i < m_scaledPoints[0].size(); ++i){
//			x[i] = (x[i] - main->getMinForVariable(main->getVariables()[i])) /
//				(main->getMaxForVariable(main->getVariables()[i]) - main->getMinForVariable(main->getVariables()[i]));
//		}

		for(unsigned int i=0; i < m_interpolationPoints.size(); ++i)
			sum += m_alphas[i] * R(i,m_interpolationPoints, x);

//		//Ausgabe skalieren:
//		sum = m_interpolationValues->getMin() + sum*(m_interpolationValues->getMax() - m_interpolationValues->getMin());
		return sum;
}

void InterpolationFunction::calculateAlphas(vector<vector<double> > points, vector<double> values){
	unsigned int size = points.size();
	int* pivot = new int[size];
	double* b = new double[size];
	double* AT = new double[size*size];

	for(unsigned int i=0;i<size;++i)
		b[i] = values[i];

	unsigned int dim = points[0].size();
	double* arr = new double[dim];

	// to call a Fortran routine from C we
	// have to transform the matrix
	// c: spaltenweise
	// fortran: zeilenweise
	for (unsigned int i=0; i<size; i++)
		for(unsigned int j=0; j<size; j++){
			for(unsigned int x=0; x<dim; x++)
				arr[x] = points[j][x];
			AT[j+size*i]=R(i,points,arr);
		}
		delete[] arr;

		int info;

		//---------------------------------------------------------------------------
		//---------------------------------------------------------------------------
		//---------------------- LAPACK: min_a (A*a - y) ----------------------------
		//INPUT: A in AT, y in b
		//OUTPUT: a in b
		int m,n;
		m=n=size;
		int nrhs=1;
		int lwork=m*n;
		double* work2 = new double[m*n + m*n];

                dgels_("N",&m,&n,&nrhs,AT,&m,b,&m,work2,&lwork,&info);
		//---------------------------------------------------------------------------
		//---------------------------------------------------------------------------
		//---------------------------------------------------------------------------

		m_alphas.resize(size);
		for(unsigned int i=0;i<size;++i)
			if(0 == info){//Ergebnis nun in b
				m_alphas[i] = b[i];
			}else{
				m_alphas[i] = 0;
		}

		delete[] pivot;
		delete[] b;
		delete[] AT;
		delete[] work2;
}

double InterpolationFunction::R(unsigned int di, const vector<vector<double> >& points, double* xj){
	float distance_sq = 0;
	float result_sq;

	for(unsigned int i=0; i < points[0].size(); ++i)
		distance_sq += (points[di][i]-xj[i])*(points[di][i]-xj[i]);

	result_sq = distance_sq + m_d*m_meanDistanceOfInterpolationPoints*m_d*m_meanDistanceOfInterpolationPoints;

	return pow(double(result_sq), double(m_mu));
}

double InterpolationFunction::distance(vector<double> x,vector<double> y){
	float sum=0;
	for(unsigned int i=0; i < x.size(); ++i)
		sum += (x[i]-y[i])*(x[i]-y[i]);
	return sqrt(sum);
}

void InterpolationFunction::calculateMeanDistance(){
	unsigned int size = m_interpolationPoints.size();
	float meanDistance=0;
	for(unsigned int i=0;i<size;++i){
		float min;
		bool firstTime = true;
		for(unsigned int j=0;j<size;++j)
			if(j!=i){
				float d = distance(m_interpolationPoints[i],m_interpolationPoints[j]);
				if(firstTime || d<min){
					min = d;
					firstTime = false;
				}
			}
			meanDistance += min;
	}

	m_meanDistanceOfInterpolationPoints = meanDistance / size;
}

QString InterpolationFunction::pjob_file(){
	return m_pjob_file;
}

QString InterpolationFunction::result(){
	return m_result;
}

QDoubleHash InterpolationFunction::findMinimum(){
	SimulatedAnnealing sa(this);
	return sa.findMinimum();
}

QDoubleHash InterpolationFunction::findMaximum(){
	SimulatedAnnealing sa(this);
	return sa.findMaximum();
}

void InterpolationFunction::remove_infs_and_nans(vector< vector<double> >& points, vector<double>& values){
	set<unsigned int> indices_to_remove;
	for(unsigned int i=0;i<values.size();i++){
		if((values[i] != values[i]) || (values[i] == numeric_limits<double>::infinity())) indices_to_remove.insert(i);
	}

	vector< vector<double> > new_points;
	vector<double> new_values;

	for(unsigned int i=0;i<values.size();i++){
		if(indices_to_remove.count(i)) continue;
		new_points.push_back(points[i]);
		new_values.push_back(values[i]);
	}

	points = new_points;
	values = new_values;
}
<commit_msg>Fixed InterpolationFunction and therefore 3D-View.<commit_after>#include "InterpolationFunction.h"
#include <QtGlobal>
#include <math.h>
#include <QtCore/QStringList>
#include "Workspace.h"
#include "SimulatedAnnealing.h"
#include <set>
#include <limits>
#include <boost/foreach.hpp>

//Optimierer: min_a (A*a - y)
extern "C"{
	int sgels_(char *trans, int *m, int *n, int * nrhs,
		float *a, int *lda, float *b, int *ldb, float *work,
		int *lwork, int *info);

	int dgels_(char *trans, int *m, int *n, int * nrhs,
		double *a, int *lda, double *b, int *ldb,
		double *work, int *lwork, int *info);
}

InterpolationFunction::InterpolationFunction(QString pjob_file, QString result)
: m_pjob_file(pjob_file), m_result(result), m_mu(0.5), m_d(0)
{
	buildParameterSorting();
	m_interpolationPoints = interpolationPoints();
	m_interpolationValues = interpolationValues();
	Q_ASSERT(m_interpolationPoints.size() == m_interpolationValues.size());
	remove_infs_and_nans(m_interpolationPoints, m_interpolationValues);
	Q_ASSERT(m_interpolationPoints.size() == m_interpolationValues.size());
	BOOST_FOREACH(std::vector<double>& point, m_interpolationPoints){
		Q_ASSERT(point.size() == m_interpolationPoints[0].size());
	}

	m_xarr = new double[m_interpolationPoints[0].size()];

	calculateMeanDistance();
	calculateAlphas(m_interpolationPoints,m_interpolationValues);
}

void InterpolationFunction::buildParameterSorting(){
	QSet< QHash<QString,double> > parameterCombinations = Workspace::getInstace().getResults().parameterCombinationsFor(m_pjob_file);
	QSet< QString > parameterNames;
	QHash<QString,double> combination;
	foreach(combination, parameterCombinations){
		QString parameterName;
		foreach(parameterName, combination.keys())
			parameterNames.insert(parameterName);
	}
	QStringList sortedParameterNames = parameterNames.toList();
	qSort(sortedParameterNames);
	for(int i=0;i<sortedParameterNames.size();++i)
		m_parameterSorting[sortedParameterNames.at(i)] = i;
}

vector< vector<double> > InterpolationFunction::interpolationPoints(){
	vector< vector<double> > result;
	QSet< QHash<QString,double> > parameterCombinations = Workspace::getInstace().getResults().parameterCombinationsFor(m_pjob_file);
	QHash<QString,double> combination;
	foreach(combination, parameterCombinations){
		QString parameterName;
		vector<double> parameterValues;
		parameterValues.resize(combination.size());
		foreach(parameterName, combination.keys())
			parameterValues[m_parameterSorting[parameterName]] = combination[parameterName];
		result.push_back(parameterValues);
	}
	return result;
}

vector<double> InterpolationFunction::interpolationValues(){
	vector<double> result;
	QSet< QHash<QString,double> > parameterCombinations = Workspace::getInstace().getResults().parameterCombinationsFor(m_pjob_file);
	QHash<QString,double> combination;
	foreach(combination, parameterCombinations){
		result.push_back(Workspace::getInstace().getResults().getValue(m_pjob_file,m_result,combination));
	}
	return result;
}

InterpolationFunction::~InterpolationFunction(){
	delete[] m_xarr;
}

double InterpolationFunction::getValue(QHash< QString, double > parameters){
	if(m_interpolationPoints.size() == 0) return 0;
    Q_ASSERT(parameters.size() == static_cast<int>(m_interpolationPoints[0].size()));
	QString parameterName;
	foreach(parameterName, parameters.keys())
	m_xarr[m_parameterSorting[parameterName]] = parameters[parameterName];

	return f(m_xarr);
}

double InterpolationFunction::f(double* x){
	//if(!m_hasSolution) return 0;

		double sum=0;
//		//x skalieren:
//		Data* main = Schlangensicht::getInstance().getMainData();
//		for(unsigned int i=0; i < m_scaledPoints[0].size(); ++i){
//			x[i] = (x[i] - main->getMinForVariable(main->getVariables()[i])) /
//				(main->getMaxForVariable(main->getVariables()[i]) - main->getMinForVariable(main->getVariables()[i]));
//		}

		for(unsigned int i=0; i < m_interpolationPoints.size(); ++i)
			sum += m_alphas[i] * R(i,m_interpolationPoints, x);

//		//Ausgabe skalieren:
//		sum = m_interpolationValues->getMin() + sum*(m_interpolationValues->getMax() - m_interpolationValues->getMin());
		return sum;
}

void InterpolationFunction::calculateAlphas(vector<vector<double> > points, vector<double> values){
	unsigned int size = points.size();
	int* pivot = new int[size];
	double* b = new double[size];
	double* AT = new double[size*size];

	for(unsigned int i=0;i<size;++i)
		b[i] = values[i];

	unsigned int dim = points[0].size();
	double* arr = new double[dim];

	// to call a Fortran routine from C we
	// have to transform the matrix
	// c: spaltenweise
	// fortran: zeilenweise
	for (unsigned int i=0; i<size; i++)
		for(unsigned int j=0; j<size; j++){
			for(unsigned int x=0; x<dim; x++)
				arr[x] = points[j][x];
			AT[j+size*i]=R(i,points,arr);
		}
		delete[] arr;

		int info;

		//---------------------------------------------------------------------------
		//---------------------------------------------------------------------------
		//---------------------- LAPACK: min_a (A*a - y) ----------------------------
		//INPUT: A in AT, y in b
		//OUTPUT: a in b
		int m,n;
		m=n=size;
		int nrhs=1;
		int lwork=m*n;
		double* work2 = new double[m*n + m*n];
                int lwork2=2*m*n;

                dgels_("N",&m,&n,&nrhs,AT,&m,b,&m,work2,&lwork2,&info);
		//---------------------------------------------------------------------------
		//---------------------------------------------------------------------------
		//---------------------------------------------------------------------------

		m_alphas.resize(size);
		for(unsigned int i=0;i<size;++i)
			if(0 == info){//Ergebnis nun in b
				m_alphas[i] = b[i];
			}else{
				m_alphas[i] = 0;
		}

		delete[] pivot;
		delete[] b;
		delete[] AT;
		delete[] work2;
}

double InterpolationFunction::R(unsigned int di, const vector<vector<double> >& points, double* xj){
	float distance_sq = 0;
	float result_sq;

	for(unsigned int i=0; i < points[0].size(); ++i)
		distance_sq += (points[di][i]-xj[i])*(points[di][i]-xj[i]);

	result_sq = distance_sq + m_d*m_meanDistanceOfInterpolationPoints*m_d*m_meanDistanceOfInterpolationPoints;

	return pow(double(result_sq), double(m_mu));
}

double InterpolationFunction::distance(vector<double> x,vector<double> y){
	float sum=0;
	for(unsigned int i=0; i < x.size(); ++i)
		sum += (x[i]-y[i])*(x[i]-y[i]);
	return sqrt(sum);
}

void InterpolationFunction::calculateMeanDistance(){
	unsigned int size = m_interpolationPoints.size();
	float meanDistance=0;
	for(unsigned int i=0;i<size;++i){
		float min;
		bool firstTime = true;
		for(unsigned int j=0;j<size;++j)
			if(j!=i){
				float d = distance(m_interpolationPoints[i],m_interpolationPoints[j]);
				if(firstTime || d<min){
					min = d;
					firstTime = false;
				}
			}
			meanDistance += min;
	}

	m_meanDistanceOfInterpolationPoints = meanDistance / size;
}

QString InterpolationFunction::pjob_file(){
	return m_pjob_file;
}

QString InterpolationFunction::result(){
	return m_result;
}

QDoubleHash InterpolationFunction::findMinimum(){
	SimulatedAnnealing sa(this);
	return sa.findMinimum();
}

QDoubleHash InterpolationFunction::findMaximum(){
	SimulatedAnnealing sa(this);
	return sa.findMaximum();
}

void InterpolationFunction::remove_infs_and_nans(vector< vector<double> >& points, vector<double>& values){
	set<unsigned int> indices_to_remove;
	for(unsigned int i=0;i<values.size();i++){
		if((values[i] != values[i]) || (values[i] == numeric_limits<double>::infinity())) indices_to_remove.insert(i);
	}

	vector< vector<double> > new_points;
	vector<double> new_values;

	for(unsigned int i=0;i<values.size();i++){
		if(indices_to_remove.count(i)) continue;
		new_points.push_back(points[i]);
		new_values.push_back(values[i]);
	}

	points = new_points;
	values = new_values;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/executors/CPUThreadPoolExecutor.h>

#include <folly/Memory.h>
#include <folly/concurrency/QueueObserver.h>
#include <folly/executors/task_queue/PriorityLifoSemMPMCQueue.h>
#include <folly/executors/task_queue/PriorityUnboundedBlockingQueue.h>
#include <folly/executors/task_queue/UnboundedBlockingQueue.h>
#include <folly/portability/GFlags.h>

DEFINE_bool(
    dynamic_cputhreadpoolexecutor,
    true,
    "CPUThreadPoolExecutor will dynamically create and destroy threads");

namespace folly {

namespace {
//  queue_alloc custom allocator is necessary until C++17
//    http://open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3396.htm
//    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65122
//    https://bugs.llvm.org/show_bug.cgi?id=22634
using default_queue = UnboundedBlockingQueue<CPUThreadPoolExecutor::CPUTask>;
using default_queue_alloc =
    AlignedSysAllocator<default_queue, FixedAlign<alignof(default_queue)>>;

constexpr folly::StringPiece executorName = "CPUThreadPoolExecutor";
} // namespace

const size_t CPUThreadPoolExecutor::kDefaultMaxQueueSize = 1 << 14;

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    std::unique_ptr<BlockingQueue<CPUTask>> taskQueue,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads,
          FLAGS_dynamic_cputhreadpoolexecutor ? 0 : numThreads,
          std::move(threadFactory)),
      taskQueue_(taskQueue.release()) {
  setNumThreads(numThreads);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    std::pair<size_t, size_t> numThreads,
    std::unique_ptr<BlockingQueue<CPUTask>> taskQueue,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads.first,
          numThreads.second,
          std::move(threadFactory)),
      taskQueue_(taskQueue.release()) {
  setNumThreads(numThreads.first);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads,
          FLAGS_dynamic_cputhreadpoolexecutor ? 0 : numThreads,
          std::move(threadFactory)),
      taskQueue_(std::allocate_shared<default_queue>(default_queue_alloc{})) {
  setNumThreads(numThreads);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    std::pair<size_t, size_t> numThreads,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads.first,
          numThreads.second,
          std::move(threadFactory)),
      taskQueue_(std::allocate_shared<default_queue>(default_queue_alloc{})) {
  setNumThreads(numThreads.first);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(size_t numThreads)
    : CPUThreadPoolExecutor(
          numThreads,
          std::make_shared<NamedThreadFactory>("CPUThreadPool")) {}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    int8_t numPriorities,
    std::shared_ptr<ThreadFactory> threadFactory)
    : CPUThreadPoolExecutor(
          numThreads,
          std::make_unique<PriorityUnboundedBlockingQueue<CPUTask>>(
              numPriorities),
          std::move(threadFactory)) {}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    int8_t numPriorities,
    size_t maxQueueSize,
    std::shared_ptr<ThreadFactory> threadFactory)
    : CPUThreadPoolExecutor(
          numThreads,
          std::make_unique<PriorityLifoSemMPMCQueue<CPUTask>>(
              numPriorities,
              maxQueueSize),
          std::move(threadFactory)) {}

CPUThreadPoolExecutor::~CPUThreadPoolExecutor() {
  deregisterThreadPoolExecutor(this);
  stop();
  CHECK(threadsToStop_ == 0);
  for (auto& observer : queueObservers_) {
    delete observer.load(std::memory_order_relaxed);
  }
}

QueueObserver* FOLLY_NULLABLE
CPUThreadPoolExecutor::getQueueObserver(int8_t pri) {
  if (!queueObserverFactory_) {
    return nullptr;
  }

  auto& slot = queueObservers_[static_cast<uint8_t>(pri)];
  if (auto observer = slot.load(std::memory_order_acquire)) {
    return observer;
  }

  // common case is only one queue, need only one observer
  if (getNumPriorities() == 1 && pri != 0) {
    return getQueueObserver(0);
  }
  QueueObserver* existingObserver = nullptr;
  QueueObserver* newObserver = queueObserverFactory_->create(pri).release();
  if (!slot.compare_exchange_strong(existingObserver, newObserver)) {
    delete newObserver;
    return existingObserver;
  } else {
    return newObserver;
  }
}

void CPUThreadPoolExecutor::add(Func func) {
  add(std::move(func), std::chrono::milliseconds(0));
}

void CPUThreadPoolExecutor::add(
    Func func,
    std::chrono::milliseconds expiration,
    Func expireCallback) {
  CPUTask task{std::move(func), expiration, std::move(expireCallback), 0};
  if (auto queueObserver = getQueueObserver(0)) {
    task.queueObserverPayload() = queueObserver->onEnqueued();
  }
  auto result = taskQueue_->add(std::move(task));
  if (!result.reusedThread) {
    ensureActiveThreads();
  }
}

void CPUThreadPoolExecutor::addWithPriority(Func func, int8_t priority) {
  add(std::move(func), priority, std::chrono::milliseconds(0));
}

void CPUThreadPoolExecutor::add(
    Func func,
    int8_t priority,
    std::chrono::milliseconds expiration,
    Func expireCallback) {
  CHECK(getNumPriorities() > 0);
  CPUTask task(
      std::move(func), expiration, std::move(expireCallback), priority);
  if (auto queueObserver = getQueueObserver(priority)) {
    task.queueObserverPayload() = queueObserver->onEnqueued();
  }
  auto result = taskQueue_->addWithPriority(std::move(task), priority);
  if (!result.reusedThread) {
    ensureActiveThreads();
  }
}

uint8_t CPUThreadPoolExecutor::getNumPriorities() const {
  return taskQueue_->getNumPriorities();
}

size_t CPUThreadPoolExecutor::getTaskQueueSize() const {
  return taskQueue_->size();
}

BlockingQueue<CPUThreadPoolExecutor::CPUTask>*
CPUThreadPoolExecutor::getTaskQueue() {
  return taskQueue_.get();
}

// threadListLock_ must be writelocked.
bool CPUThreadPoolExecutor::tryDecrToStop() {
  auto toStop = threadsToStop_.load(std::memory_order_relaxed);
  if (toStop <= 0) {
    return false;
  }
  threadsToStop_.store(toStop - 1, std::memory_order_relaxed);
  return true;
}

bool CPUThreadPoolExecutor::taskShouldStop(folly::Optional<CPUTask>& task) {
  if (tryDecrToStop()) {
    return true;
  }
  if (task) {
    return false;
  } else {
    return tryTimeoutThread();
  }
  return true;
}

void CPUThreadPoolExecutor::threadRun(ThreadPtr thread) {
  this->threadPoolHook_.registerThread();
  ExecutorBlockingGuard guard{ExecutorBlockingGuard::ForbidTag{}, executorName};

  thread->startupBaton.post();
  while (true) {
    auto task = taskQueue_->try_take_for(threadTimeout_);

    // Handle thread stopping, either by task timeout, or
    // by 'poison' task added in join() or stop().
    if (UNLIKELY(!task || task.value().poison)) {
      // Actually remove the thread from the list.
      SharedMutex::WriteHolder w{&threadListLock_};
      if (taskShouldStop(task)) {
        for (auto& o : observers_) {
          o->threadStopped(thread.get());
        }
        threadList_.remove(thread);
        stoppedThreads_.add(thread);
        return;
      } else {
        continue;
      }
    }

    if (auto queueObserver = getQueueObserver(task->queuePriority())) {
      queueObserver->onDequeued(task->queueObserverPayload());
    }
    runTask(thread, std::move(task.value()));

    if (UNLIKELY(threadsToStop_ > 0 && !isJoin_)) {
      SharedMutex::WriteHolder w{&threadListLock_};
      if (tryDecrToStop()) {
        threadList_.remove(thread);
        stoppedThreads_.add(thread);
        return;
      }
    }
  }
}

void CPUThreadPoolExecutor::stopThreads(size_t n) {
  threadsToStop_ += n;
  for (size_t i = 0; i < n; i++) {
    taskQueue_->addWithPriority(CPUTask(), Executor::LO_PRI);
  }
}

// threadListLock_ is read (or write) locked.
size_t CPUThreadPoolExecutor::getPendingTaskCountImpl() const {
  return taskQueue_->size();
}

std::unique_ptr<folly::QueueObserverFactory>
CPUThreadPoolExecutor::createQueueObserverFactory() {
  for (auto& observer : queueObservers_) {
    observer.store(nullptr, std::memory_order_release);
  }
  return QueueObserverFactory::make(
      "cpu." + getName(), taskQueue_->getNumPriorities());
}

} // namespace folly
<commit_msg>better lag detector factory caching<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * 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 <folly/executors/CPUThreadPoolExecutor.h>

#include <folly/Memory.h>
#include <folly/concurrency/QueueObserver.h>
#include <folly/executors/task_queue/PriorityLifoSemMPMCQueue.h>
#include <folly/executors/task_queue/PriorityUnboundedBlockingQueue.h>
#include <folly/executors/task_queue/UnboundedBlockingQueue.h>
#include <folly/portability/GFlags.h>

DEFINE_bool(
    dynamic_cputhreadpoolexecutor,
    true,
    "CPUThreadPoolExecutor will dynamically create and destroy threads");

namespace folly {

namespace {
//  queue_alloc custom allocator is necessary until C++17
//    http://open-std.org/JTC1/SC22/WG21/docs/papers/2012/n3396.htm
//    https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65122
//    https://bugs.llvm.org/show_bug.cgi?id=22634
using default_queue = UnboundedBlockingQueue<CPUThreadPoolExecutor::CPUTask>;
using default_queue_alloc =
    AlignedSysAllocator<default_queue, FixedAlign<alignof(default_queue)>>;

constexpr folly::StringPiece executorName = "CPUThreadPoolExecutor";
} // namespace

const size_t CPUThreadPoolExecutor::kDefaultMaxQueueSize = 1 << 14;

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    std::unique_ptr<BlockingQueue<CPUTask>> taskQueue,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads,
          FLAGS_dynamic_cputhreadpoolexecutor ? 0 : numThreads,
          std::move(threadFactory)),
      taskQueue_(taskQueue.release()) {
  setNumThreads(numThreads);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    std::pair<size_t, size_t> numThreads,
    std::unique_ptr<BlockingQueue<CPUTask>> taskQueue,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads.first,
          numThreads.second,
          std::move(threadFactory)),
      taskQueue_(taskQueue.release()) {
  setNumThreads(numThreads.first);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads,
          FLAGS_dynamic_cputhreadpoolexecutor ? 0 : numThreads,
          std::move(threadFactory)),
      taskQueue_(std::allocate_shared<default_queue>(default_queue_alloc{})) {
  setNumThreads(numThreads);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    std::pair<size_t, size_t> numThreads,
    std::shared_ptr<ThreadFactory> threadFactory)
    : ThreadPoolExecutor(
          numThreads.first,
          numThreads.second,
          std::move(threadFactory)),
      taskQueue_(std::allocate_shared<default_queue>(default_queue_alloc{})) {
  setNumThreads(numThreads.first);
  registerThreadPoolExecutor(this);
}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(size_t numThreads)
    : CPUThreadPoolExecutor(
          numThreads,
          std::make_shared<NamedThreadFactory>("CPUThreadPool")) {}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    int8_t numPriorities,
    std::shared_ptr<ThreadFactory> threadFactory)
    : CPUThreadPoolExecutor(
          numThreads,
          std::make_unique<PriorityUnboundedBlockingQueue<CPUTask>>(
              numPriorities),
          std::move(threadFactory)) {}

CPUThreadPoolExecutor::CPUThreadPoolExecutor(
    size_t numThreads,
    int8_t numPriorities,
    size_t maxQueueSize,
    std::shared_ptr<ThreadFactory> threadFactory)
    : CPUThreadPoolExecutor(
          numThreads,
          std::make_unique<PriorityLifoSemMPMCQueue<CPUTask>>(
              numPriorities,
              maxQueueSize),
          std::move(threadFactory)) {}

CPUThreadPoolExecutor::~CPUThreadPoolExecutor() {
  deregisterThreadPoolExecutor(this);
  stop();
  CHECK(threadsToStop_ == 0);
  if (getNumPriorities() == 1) {
    delete queueObservers_[0];
  } else {
    for (auto& observer : queueObservers_) {
      delete observer.load(std::memory_order_relaxed);
    }
  }
}

QueueObserver* FOLLY_NULLABLE
CPUThreadPoolExecutor::getQueueObserver(int8_t pri) {
  if (!queueObserverFactory_) {
    return nullptr;
  }

  auto& slot = queueObservers_[folly::to_unsigned(pri)];
  if (auto observer = slot.load(std::memory_order_acquire)) {
    return observer;
  }

  // common case is only one queue, need only one observer
  if (getNumPriorities() == 1 && pri != 0) {
    auto sharedObserver = getQueueObserver(0);
    slot.store(sharedObserver, std::memory_order_release);
    return sharedObserver;
  }
  QueueObserver* existingObserver = nullptr;
  auto newObserver = queueObserverFactory_->create(pri);
  if (!slot.compare_exchange_strong(existingObserver, newObserver.get())) {
    return existingObserver;
  } else {
    return newObserver.release();
  }
}

void CPUThreadPoolExecutor::add(Func func) {
  add(std::move(func), std::chrono::milliseconds(0));
}

void CPUThreadPoolExecutor::add(
    Func func,
    std::chrono::milliseconds expiration,
    Func expireCallback) {
  CPUTask task{std::move(func), expiration, std::move(expireCallback), 0};
  if (auto queueObserver = getQueueObserver(0)) {
    task.queueObserverPayload() = queueObserver->onEnqueued();
  }
  auto result = taskQueue_->add(std::move(task));
  if (!result.reusedThread) {
    ensureActiveThreads();
  }
}

void CPUThreadPoolExecutor::addWithPriority(Func func, int8_t priority) {
  add(std::move(func), priority, std::chrono::milliseconds(0));
}

void CPUThreadPoolExecutor::add(
    Func func,
    int8_t priority,
    std::chrono::milliseconds expiration,
    Func expireCallback) {
  CHECK(getNumPriorities() > 0);
  CPUTask task(
      std::move(func), expiration, std::move(expireCallback), priority);
  if (auto queueObserver = getQueueObserver(priority)) {
    task.queueObserverPayload() = queueObserver->onEnqueued();
  }
  auto result = taskQueue_->addWithPriority(std::move(task), priority);
  if (!result.reusedThread) {
    ensureActiveThreads();
  }
}

uint8_t CPUThreadPoolExecutor::getNumPriorities() const {
  return taskQueue_->getNumPriorities();
}

size_t CPUThreadPoolExecutor::getTaskQueueSize() const {
  return taskQueue_->size();
}

BlockingQueue<CPUThreadPoolExecutor::CPUTask>*
CPUThreadPoolExecutor::getTaskQueue() {
  return taskQueue_.get();
}

// threadListLock_ must be writelocked.
bool CPUThreadPoolExecutor::tryDecrToStop() {
  auto toStop = threadsToStop_.load(std::memory_order_relaxed);
  if (toStop <= 0) {
    return false;
  }
  threadsToStop_.store(toStop - 1, std::memory_order_relaxed);
  return true;
}

bool CPUThreadPoolExecutor::taskShouldStop(folly::Optional<CPUTask>& task) {
  if (tryDecrToStop()) {
    return true;
  }
  if (task) {
    return false;
  } else {
    return tryTimeoutThread();
  }
  return true;
}

void CPUThreadPoolExecutor::threadRun(ThreadPtr thread) {
  this->threadPoolHook_.registerThread();
  ExecutorBlockingGuard guard{ExecutorBlockingGuard::ForbidTag{}, executorName};

  thread->startupBaton.post();
  while (true) {
    auto task = taskQueue_->try_take_for(threadTimeout_);

    // Handle thread stopping, either by task timeout, or
    // by 'poison' task added in join() or stop().
    if (UNLIKELY(!task || task.value().poison)) {
      // Actually remove the thread from the list.
      SharedMutex::WriteHolder w{&threadListLock_};
      if (taskShouldStop(task)) {
        for (auto& o : observers_) {
          o->threadStopped(thread.get());
        }
        threadList_.remove(thread);
        stoppedThreads_.add(thread);
        return;
      } else {
        continue;
      }
    }

    if (auto queueObserver = getQueueObserver(task->queuePriority())) {
      queueObserver->onDequeued(task->queueObserverPayload());
    }
    runTask(thread, std::move(task.value()));

    if (UNLIKELY(threadsToStop_ > 0 && !isJoin_)) {
      SharedMutex::WriteHolder w{&threadListLock_};
      if (tryDecrToStop()) {
        threadList_.remove(thread);
        stoppedThreads_.add(thread);
        return;
      }
    }
  }
}

void CPUThreadPoolExecutor::stopThreads(size_t n) {
  threadsToStop_ += n;
  for (size_t i = 0; i < n; i++) {
    taskQueue_->addWithPriority(CPUTask(), Executor::LO_PRI);
  }
}

// threadListLock_ is read (or write) locked.
size_t CPUThreadPoolExecutor::getPendingTaskCountImpl() const {
  return taskQueue_->size();
}

std::unique_ptr<folly::QueueObserverFactory>
CPUThreadPoolExecutor::createQueueObserverFactory() {
  for (auto& observer : queueObservers_) {
    observer.store(nullptr, std::memory_order_release);
  }
  return QueueObserverFactory::make(
      "cpu." + getName(), taskQueue_->getNumPriorities());
}

} // namespace folly
<|endoftext|>


<commit_before>/* main.cpp - CS 472 Project #3: Genetic Programming
 * Copyright 2014 Andrew Schwartzmeyer
 */

#include <cstdlib>
#include <chrono>
#include <ctime>
#include <iostream>
#include <tuple>

#include "algorithm/algorithm.hpp"
#include "individual/individual.hpp"
#include "options/options.hpp"
#include "random_generator/random_generator.hpp"
#include "trials/trials.hpp"

int
main(int argc, char* argv[])
{
  // Retrieve program options.
  const options::Options options = options::parse(argc, argv);

  // Chrono start, end, and Unix time variables.
  std::chrono::time_point<std::chrono::system_clock> start, end;
  std::time_t time = std::time(nullptr);

  // Begin timing trials.
  start = std::chrono::system_clock::now();

  // Run trials and save best Individual.
  const std::tuple<int, individual::Individual> best =
    trials::run(time, options);

  // End timing trials.
  end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end - start;

  // Print total time info and which trial was best.
  std::cout << "Total elapsed time: " << elapsed_seconds.count() << "s\n"
	    << "Average time: " << elapsed_seconds.count() / options.trials
	    << "s\nBest trial: " << time << "_"
	    << std::get<0>(best) << "\n"
	    << std::get<1>(best).print();

  return EXIT_SUCCESS;
}
<commit_msg>Learned about std::tie<commit_after>/* main.cpp - CS 472 Project #3: Genetic Programming
 * Copyright 2014 Andrew Schwartzmeyer
 */

#include <cstdlib>
#include <chrono>
#include <ctime>
#include <iostream>
#include <tuple>

#include "algorithm/algorithm.hpp"
#include "individual/individual.hpp"
#include "options/options.hpp"
#include "random_generator/random_generator.hpp"
#include "trials/trials.hpp"

int
main(int argc, char* argv[])
{
  // Retrieve program options.
  const options::Options options = options::parse(argc, argv);

  // Chrono start, end, and Unix time variables.
  std::chrono::time_point<std::chrono::system_clock> start, end;
  std::time_t time = std::time(nullptr);

  // Begin timing trials.
  start = std::chrono::system_clock::now();

  // Run trials and save best Individual.
  int best_index;
  individual::Individual best;
  std::tie(best_index, best) = trials::run(time, options);

  // End timing trials.
  end = std::chrono::system_clock::now();
  std::chrono::duration<double> elapsed_seconds = end - start;

  // Print total time info and which trial was best.
  std::cout << "Total elapsed time: " << elapsed_seconds.count() << "s\n"
	    << "Average time: " << elapsed_seconds.count() / options.trials
	    << "s\nBest trial: " << time << "_"
	    << best_index << "\n"
	    << best.print();

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: FormattedField.hxx,v $
 *
 *  $Revision: 1.17 $
 *
 *  last change: $Author: obo $ $Date: 2007-03-09 13:26:13 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _FORMS_FORMATTEDFIELD_HXX_
#define _FORMS_FORMATTEDFIELD_HXX_

#ifndef _FORMS_EDITBASE_HXX_
#include "EditBase.hxx"
#endif

#ifndef _COMPHELPER_PROPERTY_MULTIPLEX_HXX_
#include <comphelper/propmultiplex.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef FORMS_ERRORBROADCASTER_HXX
#include "errorbroadcaster.hxx"
#endif

//.........................................................................
namespace frm
{

    //==================================================================
    //= OFormattedModel
    //==================================================================

    class OFormattedModel
                    :public OEditBaseModel
                    ,public OErrorBroadcaster
    {
        // das Original, falls ich die Format-Properties meines aggregierten Models gefaket, d.h. von dem Feld, an das
        // ich gebunden bin, weitergereicht habe (nur gueltig wenn loaded)
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>   m_xOriginalFormatter;
        ::com::sun::star::util::Date        m_aNullDate;
        ::com::sun::star::uno::Any          m_aSaveValue;

        sal_Int32                           m_nFieldType;
        sal_Int16                           m_nKeyType;
        sal_Bool                            m_bOriginalNumeric      : 1,
                                            m_bNumeric              : 1;    // analog fuer TreatAsNumeric-Property

    protected:
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcDefaultFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormatsSupplier() const;
        sal_Int32 calcFormatKey() const;

        DECLARE_DEFAULT_LEAF_XTOR( OFormattedModel );

        friend InterfaceRef SAL_CALL OFormattedModel_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        friend class OFormattedFieldWrapper;

    protected:
    // XInterface
        DECLARE_UNO3_AGG_DEFAULTS( OFormattedModel, OEditBaseModel );

    // XTypeProvider
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // XAggregation
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

    // OComponentHelper
        virtual void SAL_CALL disposing();

    // XServiceInfo
        IMPLEMENTATION_NAME(OFormattedModel);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // XPersistObject
        virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertySet
        virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
        virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue,
                                              sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
                                            throw(::com::sun::star::lang::IllegalArgumentException);
        virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception);

    // XLoadListener
        virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertyState
        void setPropertyToDefaultByHandle(sal_Int32 nHandle);
        ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const;

        void SAL_CALL setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

        // OControlModel's property handling
        virtual void describeFixedProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
        ) const;
        virtual void describeAggregateProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
        ) const;

    // XPropertyChangeListener
        virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException);

    // prevent method hiding
        using OEditBaseModel::disposing;
        using OEditBaseModel::getFastPropertyValue;

    protected:
        virtual sal_uInt16 getPersistenceFlags() const;
            // as we have an own version handling for persistence

        // OBoundControlModel overridables
        virtual ::com::sun::star::uno::Any
                            translateDbColumnToControlValue( );
        virtual sal_Bool    commitControlValueToDbColumn( bool _bPostReset );

        virtual ::com::sun::star::uno::Any
                            translateExternalValueToControlValue( ) const;
        virtual ::com::sun::star::uno::Any
                            translateControlValueToExternalValue( ) const;
        virtual void onConnectedExternalValue( );

        virtual ::com::sun::star::uno::Any
                            getDefaultForReset() const;

        virtual void        onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm );
        virtual void        onDisconnectedDbColumn();

        virtual sal_Bool    approveValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding );

    protected:
        /** retrieves the type which should be used to communicate with the current
            external binding

            The type depends on the current number format, and the types which are supported
            by the current external binding. As a least fallback, |double|'s type is returned.
            (In approveValueBinding, we ensure that only bindings supporting |double|'s are
            accepted.)

            @precond hasExternalValueBinding returns <TRUE/>
        */
        ::com::sun::star::uno::Type
                            getExternalValueType() const;

    private:
        DECLARE_XCLONEABLE();

        void implConstruct();

        void    updateFormatterNullDate();
    };

    //==================================================================
    //= OFormattedControl
    //==================================================================
    typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XKeyListener> OFormattedControl_BASE;
    class OFormattedControl :    public OBoundControl
                                ,public OFormattedControl_BASE
    {
        sal_uInt32              m_nKeyEvent;

    public:
        OFormattedControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        virtual ~OFormattedControl();

        DECLARE_UNO3_AGG_DEFAULTS(OFormattedControl, OBoundControl);
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // ::com::sun::star::lang::XServiceInfo
        IMPLEMENTATION_NAME(OFormattedControl);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // ::com::sun::star::lang::XEventListener
        virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XKeyListener
        virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XControl
        virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException);

    // disambiguation
        using OBoundControl::disposing;

    private:
        DECL_LINK( OnKeyPressed, void* );
    };

//.........................................................................
}
//.........................................................................

#endif // _FORMS_FORMATTEDFIELD_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.17.82); FILE MERGED 2008/04/01 15:16:30 thb 1.17.82.3: #i85898# Stripping all external header guards 2008/04/01 12:30:22 thb 1.17.82.2: #i85898# Stripping all external header guards 2008/03/31 13:11:33 rt 1.17.82.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: FormattedField.hxx,v $
 * $Revision: 1.18 $
 *
 * 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.
 *
 ************************************************************************/

#ifndef _FORMS_FORMATTEDFIELD_HXX_
#define _FORMS_FORMATTEDFIELD_HXX_

#include "EditBase.hxx"
#include <comphelper/propmultiplex.hxx>
#include <cppuhelper/implbase1.hxx>
#include "errorbroadcaster.hxx"

//.........................................................................
namespace frm
{

    //==================================================================
    //= OFormattedModel
    //==================================================================

    class OFormattedModel
                    :public OEditBaseModel
                    ,public OErrorBroadcaster
    {
        // das Original, falls ich die Format-Properties meines aggregierten Models gefaket, d.h. von dem Feld, an das
        // ich gebunden bin, weitergereicht habe (nur gueltig wenn loaded)
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>   m_xOriginalFormatter;
        ::com::sun::star::util::Date        m_aNullDate;
        ::com::sun::star::uno::Any          m_aSaveValue;

        sal_Int32                           m_nFieldType;
        sal_Int16                           m_nKeyType;
        sal_Bool                            m_bOriginalNumeric      : 1,
                                            m_bNumeric              : 1;    // analog fuer TreatAsNumeric-Property

    protected:
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcDefaultFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormatsSupplier() const;
        sal_Int32 calcFormatKey() const;

        DECLARE_DEFAULT_LEAF_XTOR( OFormattedModel );

        friend InterfaceRef SAL_CALL OFormattedModel_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        friend class OFormattedFieldWrapper;

    protected:
    // XInterface
        DECLARE_UNO3_AGG_DEFAULTS( OFormattedModel, OEditBaseModel );

    // XTypeProvider
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // XAggregation
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

    // OComponentHelper
        virtual void SAL_CALL disposing();

    // XServiceInfo
        IMPLEMENTATION_NAME(OFormattedModel);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // XPersistObject
        virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertySet
        virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
        virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue,
                                              sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
                                            throw(::com::sun::star::lang::IllegalArgumentException);
        virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception);

    // XLoadListener
        virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertyState
        void setPropertyToDefaultByHandle(sal_Int32 nHandle);
        ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const;

        void SAL_CALL setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

        // OControlModel's property handling
        virtual void describeFixedProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
        ) const;
        virtual void describeAggregateProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
        ) const;

    // XPropertyChangeListener
        virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException);

    // prevent method hiding
        using OEditBaseModel::disposing;
        using OEditBaseModel::getFastPropertyValue;

    protected:
        virtual sal_uInt16 getPersistenceFlags() const;
            // as we have an own version handling for persistence

        // OBoundControlModel overridables
        virtual ::com::sun::star::uno::Any
                            translateDbColumnToControlValue( );
        virtual sal_Bool    commitControlValueToDbColumn( bool _bPostReset );

        virtual ::com::sun::star::uno::Any
                            translateExternalValueToControlValue( ) const;
        virtual ::com::sun::star::uno::Any
                            translateControlValueToExternalValue( ) const;
        virtual void onConnectedExternalValue( );

        virtual ::com::sun::star::uno::Any
                            getDefaultForReset() const;

        virtual void        onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm );
        virtual void        onDisconnectedDbColumn();

        virtual sal_Bool    approveValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding );

    protected:
        /** retrieves the type which should be used to communicate with the current
            external binding

            The type depends on the current number format, and the types which are supported
            by the current external binding. As a least fallback, |double|'s type is returned.
            (In approveValueBinding, we ensure that only bindings supporting |double|'s are
            accepted.)

            @precond hasExternalValueBinding returns <TRUE/>
        */
        ::com::sun::star::uno::Type
                            getExternalValueType() const;

    private:
        DECLARE_XCLONEABLE();

        void implConstruct();

        void    updateFormatterNullDate();
    };

    //==================================================================
    //= OFormattedControl
    //==================================================================
    typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XKeyListener> OFormattedControl_BASE;
    class OFormattedControl :    public OBoundControl
                                ,public OFormattedControl_BASE
    {
        sal_uInt32              m_nKeyEvent;

    public:
        OFormattedControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        virtual ~OFormattedControl();

        DECLARE_UNO3_AGG_DEFAULTS(OFormattedControl, OBoundControl);
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // ::com::sun::star::lang::XServiceInfo
        IMPLEMENTATION_NAME(OFormattedControl);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // ::com::sun::star::lang::XEventListener
        virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XKeyListener
        virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XControl
        virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException);

    // disambiguation
        using OBoundControl::disposing;

    private:
        DECL_LINK( OnKeyPressed, void* );
    };

//.........................................................................
}
//.........................................................................

#endif // _FORMS_FORMATTEDFIELD_HXX_

<|endoftext|>


<commit_before>/*************************************************************************
 *
 * 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: FormattedField.hxx,v $
 * $Revision: 1.18 $
 *
 * 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.
 *
 ************************************************************************/

#ifndef _FORMS_FORMATTEDFIELD_HXX_
#define _FORMS_FORMATTEDFIELD_HXX_

#include "EditBase.hxx"
#include <comphelper/propmultiplex.hxx>
#include <cppuhelper/implbase1.hxx>
#include "errorbroadcaster.hxx"

//.........................................................................
namespace frm
{

    //==================================================================
    //= OFormattedModel
    //==================================================================

    class OFormattedModel
                    :public OEditBaseModel
                    ,public OErrorBroadcaster
    {
        // das Original, falls ich die Format-Properties meines aggregierten Models gefaket, d.h. von dem Feld, an das
        // ich gebunden bin, weitergereicht habe (nur gueltig wenn loaded)
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>   m_xOriginalFormatter;
        ::com::sun::star::util::Date        m_aNullDate;
        ::com::sun::star::uno::Any          m_aSaveValue;

        sal_Int32                           m_nFieldType;
        sal_Int16                           m_nKeyType;
        sal_Bool                            m_bOriginalNumeric      : 1,
                                            m_bNumeric              : 1;    // analog fuer TreatAsNumeric-Property

    protected:
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcDefaultFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormatsSupplier() const;
        sal_Int32 calcFormatKey() const;

        DECLARE_DEFAULT_LEAF_XTOR( OFormattedModel );

        friend InterfaceRef SAL_CALL OFormattedModel_CreateInstance(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        friend class OFormattedFieldWrapper;

    protected:
    // XInterface
        DECLARE_UNO3_AGG_DEFAULTS( OFormattedModel, OEditBaseModel );

    // XTypeProvider
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // XAggregation
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

    // OComponentHelper
        virtual void SAL_CALL disposing();

    // XServiceInfo
        IMPLEMENTATION_NAME(OFormattedModel);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // XPersistObject
        virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertySet
        virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
        virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue,
                                              sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
                                            throw(::com::sun::star::lang::IllegalArgumentException);
        virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception);

    // XLoadListener
        virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertyState
        void setPropertyToDefaultByHandle(sal_Int32 nHandle);
        ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const;

        void SAL_CALL setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

        // OControlModel's property handling
        virtual void describeFixedProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
        ) const;
        virtual void describeAggregateProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
        ) const;

    // XPropertyChangeListener
        virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException);

    // prevent method hiding
        using OEditBaseModel::disposing;
        using OEditBaseModel::getFastPropertyValue;

    protected:
        virtual sal_uInt16 getPersistenceFlags() const;
            // as we have an own version handling for persistence

        // OBoundControlModel overridables
        virtual ::com::sun::star::uno::Any
                            translateDbColumnToControlValue( );
        virtual sal_Bool    commitControlValueToDbColumn( bool _bPostReset );

        virtual ::com::sun::star::uno::Any
                            translateExternalValueToControlValue( ) const;
        virtual ::com::sun::star::uno::Any
                            translateControlValueToExternalValue( ) const;
        virtual void onConnectedExternalValue( );

        virtual ::com::sun::star::uno::Any
                            getDefaultForReset() const;

        virtual void        onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm );
        virtual void        onDisconnectedDbColumn();

        virtual sal_Bool    approveValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding );

    protected:
        /** retrieves the type which should be used to communicate with the current
            external binding

            The type depends on the current number format, and the types which are supported
            by the current external binding. As a least fallback, |double|'s type is returned.
            (In approveValueBinding, we ensure that only bindings supporting |double|'s are
            accepted.)

            @precond hasExternalValueBinding returns <TRUE/>
        */
        ::com::sun::star::uno::Type
                            getExternalValueType() const;

    private:
        DECLARE_XCLONEABLE();

        void implConstruct();

        void    updateFormatterNullDate();
    };

    //==================================================================
    //= OFormattedControl
    //==================================================================
    typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XKeyListener> OFormattedControl_BASE;
    class OFormattedControl :    public OBoundControl
                                ,public OFormattedControl_BASE
    {
        sal_uInt32              m_nKeyEvent;

    public:
        OFormattedControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        virtual ~OFormattedControl();

        DECLARE_UNO3_AGG_DEFAULTS(OFormattedControl, OBoundControl);
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // ::com::sun::star::lang::XServiceInfo
        IMPLEMENTATION_NAME(OFormattedControl);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // ::com::sun::star::lang::XEventListener
        virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XKeyListener
        virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XControl
        virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException);

    // disambiguation
        using OBoundControl::disposing;

    private:
        DECL_LINK( OnKeyPressed, void* );
    };

//.........................................................................
}
//.........................................................................

#endif // _FORMS_FORMATTEDFIELD_HXX_

<commit_msg>INTEGRATION: CWS dba30b (1.17.76); FILE MERGED 2008/04/15 21:52:44 fs 1.17.76.2: RESYNC: (1.17-1.18); FILE MERGED 2008/02/26 08:28:58 fs 1.17.76.1: remove unused code Issue number:  #i86305# Submitted by:  cmc@openoffice.org Reviewed by:   frank.schoenheit@sun.com<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: FormattedField.hxx,v $
 * $Revision: 1.19 $
 *
 * 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.
 *
 ************************************************************************/

#ifndef _FORMS_FORMATTEDFIELD_HXX_
#define _FORMS_FORMATTEDFIELD_HXX_

#include "EditBase.hxx"
#include <comphelper/propmultiplex.hxx>
#include <cppuhelper/implbase1.hxx>
#include "errorbroadcaster.hxx"

//.........................................................................
namespace frm
{

    //==================================================================
    //= OFormattedModel
    //==================================================================

    class OFormattedModel
                    :public OEditBaseModel
                    ,public OErrorBroadcaster
    {
        // das Original, falls ich die Format-Properties meines aggregierten Models gefaket, d.h. von dem Feld, an das
        // ich gebunden bin, weitergereicht habe (nur gueltig wenn loaded)
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>   m_xOriginalFormatter;
        ::com::sun::star::util::Date        m_aNullDate;
        ::com::sun::star::uno::Any          m_aSaveValue;

        sal_Int32                           m_nFieldType;
        sal_Int16                           m_nKeyType;
        sal_Bool                            m_bOriginalNumeric      : 1,
                                            m_bNumeric              : 1;    // analog fuer TreatAsNumeric-Property

    protected:
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcDefaultFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormFormatsSupplier() const;
        ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier>  calcFormatsSupplier() const;

        DECLARE_DEFAULT_LEAF_XTOR( OFormattedModel );

        friend class OFormattedFieldWrapper;

    protected:
    // XInterface
        DECLARE_UNO3_AGG_DEFAULTS( OFormattedModel, OEditBaseModel );

    // XTypeProvider
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // XAggregation
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

    // OComponentHelper
        virtual void SAL_CALL disposing();

    // XServiceInfo
        IMPLEMENTATION_NAME(OFormattedModel);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // XPersistObject
        virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
        virtual ::rtl::OUString SAL_CALL getServiceName() throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertySet
        virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
        virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue,
                                              sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
                                            throw(::com::sun::star::lang::IllegalArgumentException);
        virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw ( ::com::sun::star::uno::Exception);

    // XLoadListener
        virtual void SAL_CALL loaded(const ::com::sun::star::lang::EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException);

    // XPropertyState
        void setPropertyToDefaultByHandle(sal_Int32 nHandle);
        ::com::sun::star::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const;

        void SAL_CALL setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        ::com::sun::star::uno::Any SAL_CALL getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

        // OControlModel's property handling
        virtual void describeFixedProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps
        ) const;
        virtual void describeAggregateProperties(
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps
        ) const;

    // XPropertyChangeListener
        virtual void _propertyChanged(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException);

    // prevent method hiding
        using OEditBaseModel::disposing;
        using OEditBaseModel::getFastPropertyValue;

    protected:
        virtual sal_uInt16 getPersistenceFlags() const;
            // as we have an own version handling for persistence

        // OBoundControlModel overridables
        virtual ::com::sun::star::uno::Any
                            translateDbColumnToControlValue( );
        virtual sal_Bool    commitControlValueToDbColumn( bool _bPostReset );

        virtual ::com::sun::star::uno::Any
                            translateExternalValueToControlValue( ) const;
        virtual ::com::sun::star::uno::Any
                            translateControlValueToExternalValue( ) const;
        virtual void onConnectedExternalValue( );

        virtual ::com::sun::star::uno::Any
                            getDefaultForReset() const;

        virtual void        onConnectedDbColumn( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxForm );
        virtual void        onDisconnectedDbColumn();

        virtual sal_Bool    approveValueBinding( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XValueBinding >& _rxBinding );

    protected:
        /** retrieves the type which should be used to communicate with the current
            external binding

            The type depends on the current number format, and the types which are supported
            by the current external binding. As a least fallback, |double|'s type is returned.
            (In approveValueBinding, we ensure that only bindings supporting |double|'s are
            accepted.)

            @precond hasExternalValueBinding returns <TRUE/>
        */
        ::com::sun::star::uno::Type
                            getExternalValueType() const;

    private:
        DECLARE_XCLONEABLE();

        void implConstruct();

        void    updateFormatterNullDate();
    };

    //==================================================================
    //= OFormattedControl
    //==================================================================
    typedef ::cppu::ImplHelper1< ::com::sun::star::awt::XKeyListener> OFormattedControl_BASE;
    class OFormattedControl :    public OBoundControl
                                ,public OFormattedControl_BASE
    {
        sal_uInt32              m_nKeyEvent;

    public:
        OFormattedControl(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);
        virtual ~OFormattedControl();

        DECLARE_UNO3_AGG_DEFAULTS(OFormattedControl, OBoundControl);
        virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation(const ::com::sun::star::uno::Type& _rType) throw(::com::sun::star::uno::RuntimeException);

        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> _getTypes();

    // ::com::sun::star::lang::XServiceInfo
        IMPLEMENTATION_NAME(OFormattedControl);
        virtual StringSequence SAL_CALL getSupportedServiceNames() throw();

    // ::com::sun::star::lang::XEventListener
        virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XKeyListener
        virtual void SAL_CALL keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL keyReleased(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException);

    // ::com::sun::star::awt::XControl
        virtual void SAL_CALL setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException);

    // disambiguation
        using OBoundControl::disposing;

    private:
        DECL_LINK( OnKeyPressed, void* );
    };

//.........................................................................
}
//.........................................................................

#endif // _FORMS_FORMATTEDFIELD_HXX_

<|endoftext|>


<commit_before>#include <iostream>
#include <memory>
#include <vector>
#include <unordered_map>

#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>

using namespace std;

template<typename T>
T clamp(T val, T from, T to) { return std::max(from, std::min(to, val)); }

struct Color3 { float r, g, b; };

class Size
{
public:
    Size(int pixels) : _pixels(pixels) {}
    Size(float percents)
        : _percents(percents), _is_pixels(false) {}

    static Size All() { return Size(1.0f); }
    static Size Nth(int n) { return Size(1.0f / n); }

    int to_pixels(int base_pixels) const
    {
        if (_is_pixels) return clamp(_pixels, 0, base_pixels);
        else return (int) (_percents * base_pixels);
    }

    bool is_const() const { return _is_pixels; }
    float get_percents() const { return _percents; }
    int get_pixels() const { return _pixels; }

private:
    int _pixels;
    float _percents;
    bool _is_pixels = true;
};

struct Size2 { Size x, y; };
struct Int2 { int x, y; };
struct Rect { Int2 position, size; };
struct Margin
{
    int left, right, top, bottom;

    Margin(int v) : left(v), right(v), top(v), bottom(v) {}
    Margin(int x, int y) : left(x), right(x), top(y), bottom(y) {}
    Margin(int left, int right, int top, int bottom)
        : left(left), right(right), top(top), bottom(bottom) {}

    Margin operator-()
    {
        return { -left, -right, -top, -bottom };
    }

    Rect apply(const Rect& r) const
    {
        return { { r.position.x + left, r.position.y + top },
                 { r.size.x + left + right, r.size.y + top + bottom } };
    }
};

enum class MouseButton
{
    left,
    middle,
    right
};

enum class MouseState
{
    down,
    up
};

class IVisualElement
{
public:
    virtual Rect arrange(const Rect& origin) = 0;
    virtual void render(const Rect& origin) = 0;
    virtual const Margin& get_margin() const = 0;
    virtual const Size2& get_size() const = 0;

    virtual void UpdateMousePosition(Int2 cursor) = 0;
    virtual void UpdateMouseState(MouseButton button, MouseState state) = 0;
    virtual void UpdateMouseScroll(Int2 scroll) = 0;

    virtual ~IVisualElement() {}
};

class MouseEventsHandler : public virtual IVisualElement
{
public:
    virtual void UpdateMousePosition(Int2 cursor) {};
    virtual void UpdateMouseState(MouseButton button, MouseState state) {};
    virtual void UpdateMouseScroll(Int2 scroll) {};
};

class ControlBase : public virtual IVisualElement,
                    public MouseEventsHandler
{
public:
    ControlBase(const Size2& position,
                const Size2& size,
                const Margin& margin)
        : _position(position), _size(size), _margin(margin)
    {}

    Rect arrange(const Rect& origin) override
    {
        auto x0 = _position.x.to_pixels(origin.size.x) + _margin.left;
        auto y0 = _position.y.to_pixels(origin.size.y) + _margin.top;

        auto w = std::min(_size.x.to_pixels(origin.size.x),
                          origin.size.x - _margin.right - _margin.left);
        auto h = std::min(_size.y.to_pixels(origin.size.y),
                          origin.size.y - _margin.bottom - _margin.top);

        x0 += origin.position.x;
        y0 += origin.position.y;

        return { { x0, y0 }, { w, h } };
    }

    const Margin& get_margin() const override { return _margin; }
    const Size2& get_size() const override { return _size; }

private:
    Size2 _position;
    Size2 _size;
    Margin _margin;
};

class Button : public ControlBase
{
public:
    Button(const Size2& position,
           const Size2& size,
           const Margin& margin,
           const Color3& color)
        : ControlBase(position, size, margin), _color(color)
    {}

    void render(const Rect& origin) override
    {
        glBegin(GL_QUADS);
        glColor3f(_color.r, _color.g, _color.b);

        auto rect = arrange(origin);

        glVertex2i(rect.position.x, rect.position.y);
        glVertex2i(rect.position.x, rect.position.y + rect.size.y);
        glVertex2i(rect.position.x + rect.size.x,
                   rect.position.y + rect.size.y);
        glVertex2i(rect.position.x + rect.size.x,
                   rect.position.y);

        glEnd();
    }

private:
    Color3 _color;
};

enum class Orientation
{
    vertical,
    horizontal
};

class Container : public ControlBase
{
public:
    Container(const Size2& position,
              const Size2& size,
              const Margin& margin,
              Orientation orientation = Orientation::vertical)
        : ControlBase(position, size, margin), _orientation(orientation)
    {}

    void add_item(std::unique_ptr<IVisualElement> item)
    {
        _content.push_back(std::move(item));
    }

    void render(const Rect& origin) override
    {
        auto rect = arrange(origin);

        Size Size2::* field;
        int Int2::* ifield;
        if (_orientation == Orientation::vertical) {
            field = &Size2::y;
            ifield = &Int2::y;
        } else {
            field = &Size2::x;
            ifield = &Int2::x;
        }

        // first, scan items, map the "greedy" ones wanting relative portion
        std::vector<IVisualElement*> greedy;
        std::unordered_map<IVisualElement*, int> sizes;
        auto sum = 0;
        for (auto& p : _content) {
            auto p_rect = p->arrange(rect);
            auto p_total = p->get_margin().apply(p_rect);

            if ((p->get_size().*field).is_const()) {
                auto pixels = (p->get_size().*field).get_pixels();
                sum += pixels;
                sizes[p.get()] = pixels;
            } else {
                greedy.push_back(p.get());
            }
        }

        auto rest = std::max(rect.size.*ifield - sum, 0);
        float total_parts = 0;
        for (auto ptr : greedy) {
            total_parts += (ptr->get_size().*field).get_percents();
        }
        for (auto ptr : greedy) {
            auto f = ((ptr->get_size().*field).get_percents() / total_parts);
            sizes[ptr] = (int) (rest * f);
        }

        sum = rect.position.*ifield;
        for (auto& p : _content) {
            auto new_origin = rect;
            (new_origin.position.*ifield) = sum;
            (new_origin.size.*ifield) = sizes[p.get()];
            sum += sizes[p.get()];
            p->render(new_origin);
        }
    }

private:
    std::vector<std::unique_ptr<IVisualElement>> _content;
    Orientation _orientation;
};

int main(int argc, char * argv[]) try
{
    glfwInit();
    GLFWwindow * win = glfwCreateWindow(1280, 960, "main", 0, 0);
    glfwMakeContextCurrent(win);

    Color3 redish { 0.8f, 0.5f, 0.6f };

    Container c( { 0, 0 }, { 300, 1.0f }, { 5, 5, 5, 5 } );
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 1.0f }, { 5, 5, 5, 5 }, redish )));
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));

    glfwSetWindowUserPointer(win, &c);
    glfwSetCursorPosCallback(win, [](GLFWwindow * w, double x, double y) {
        auto ui_element = (IVisualElement*)glfwGetWindowUserPointer(w);
        ui_element->UpdateMousePosition({ (int)x, (int)y });
    });
    glfwSetScrollCallback(win, [](GLFWwindow * w, double x, double y) {
        auto ui_element = (IVisualElement*)glfwGetWindowUserPointer(w);
        ui_element->UpdateMouseScroll({ (int)x, (int)y });
    });
    glfwSetMouseButtonCallback(win, [](GLFWwindow * w, int button, int action, int mods)
    {
        auto ui_element = (IVisualElement*)glfwGetWindowUserPointer(w);
        MouseButton button_type;
        switch(button)
        {
        case GLFW_MOUSE_BUTTON_RIGHT:
            button_type = MouseButton::right; break;
        case GLFW_MOUSE_BUTTON_LEFT:
            button_type = MouseButton::left; break;
        case GLFW_MOUSE_BUTTON_MIDDLE:
            button_type = MouseButton::middle; break;
        default:
            button_type = MouseButton::left;
        };

        MouseState mouse_state;
        switch(action)
        {
        case GLFW_PRESS:
            mouse_state = MouseState::up; break;
        case GLFW_RELEASE:
            mouse_state = MouseState::down; break;
        default:
            mouse_state = MouseState::up;
        };

        ui_element->UpdateMouseState(button_type, mouse_state);
    });

    while (!glfwWindowShouldClose(win))
    {
        glfwPollEvents();

        int w,h;
        glfwGetFramebufferSize(win, &w, &h);
        glViewport(0, 0, w, h);
        glClear(GL_COLOR_BUFFER_BIT);

        glPushMatrix();
        glfwGetWindowSize(win, &w, &h);
        glOrtho(0, w, h, 0, -1, +1);

        Rect origin { { 0, 0 }, { w, h } };

        c.render(origin);

        glPopMatrix();
        glfwSwapBuffers(win);
    }

    glfwDestroyWindow(win);
    glfwTerminate();
    return 0;
}
catch(const std::exception & e)
{
    std::cerr << e.what() << std::endl;
    return -1;
}
<commit_msg>adding support for basic clicking and double-clicking<commit_after>#include <iostream>
#include <memory>
#include <vector>
#include <unordered_map>
#include <chrono>
#include <map>

#define GLFW_INCLUDE_GLU
#include <GLFW/glfw3.h>

using namespace std;

template<typename T>
T clamp(T val, T from, T to) { return std::max(from, std::min(to, val)); }

struct Color3 { float r, g, b; };

class Size
{
public:
    Size(int pixels) : _pixels(pixels) {}
    Size(float percents)
        : _percents(percents), _is_pixels(false) {}

    static Size All() { return Size(1.0f); }
    static Size Nth(int n) { return Size(1.0f / n); }

    int to_pixels(int base_pixels) const
    {
        if (_is_pixels) return clamp(_pixels, 0, base_pixels);
        else return (int) (_percents * base_pixels);
    }

    bool is_const() const { return _is_pixels; }
    float get_percents() const { return _percents; }
    int get_pixels() const { return _pixels; }

private:
    int _pixels;
    float _percents;
    bool _is_pixels = true;
};

struct Size2 { Size x, y; };
struct Int2 { int x, y; };
struct Rect { Int2 position, size; };
struct Margin
{
    int left, right, top, bottom;

    Margin(int v) : left(v), right(v), top(v), bottom(v) {}
    Margin(int x, int y) : left(x), right(x), top(y), bottom(y) {}
    Margin(int left, int right, int top, int bottom)
        : left(left), right(right), top(top), bottom(bottom) {}

    Margin operator-()
    {
        return { -left, -right, -top, -bottom };
    }

    Rect apply(const Rect& r) const
    {
        return { { r.position.x + left, r.position.y + top },
                 { r.size.x + left + right, r.size.y + top + bottom } };
    }
};

enum class MouseButton
{
    left,
    middle,
    right
};

enum class MouseState
{
    down,
    up
};

class IVisualElement
{
public:
    virtual Rect arrange(const Rect& origin) = 0;
    virtual void render(const Rect& origin) = 0;
    virtual const Margin& get_margin() const = 0;
    virtual const Size2& get_size() const = 0;

    virtual void update_mouse_position(Int2 cursor) = 0;
    virtual void update_mouse_state(MouseButton button, MouseState state) = 0;
    virtual void update_mouse_scroll(Int2 scroll) = 0;

    virtual ~IVisualElement() {}
};

typedef std::chrono::time_point<std::chrono::high_resolution_clock> TimePoint;

class MouseEventsHandler : public virtual IVisualElement
{
public:
    MouseEventsHandler()
        : _on_double_click([](){})
    {
        _state[MouseButton::left] = _state[MouseButton::right] =
        _state[MouseButton::middle] = MouseState::up;

        _on_click[MouseButton::left] = _on_click[MouseButton::right] =
        _on_click[MouseButton::middle] = [](){};

        auto now = std::chrono::high_resolution_clock::now();
        _last_update[MouseButton::left] = _last_update[MouseButton::right] =
        _last_update[MouseButton::middle] = now;

        _last_click[MouseButton::left] = _last_click[MouseButton::right] =
        _last_click[MouseButton::middle] = now;
    }

    void update_mouse_position(Int2 cursor) override {};

    void update_mouse_state(MouseButton button, MouseState state) override {
        auto now = std::chrono::high_resolution_clock::now();
        auto curr = _state[button];
        if (curr != state)
        {
            auto ms = std::chrono::duration_cast<std::chrono::milliseconds>
                            (now - _last_update[button]).count();
            if (ms < CLICK_TIME_MS)
            {
                if (state == MouseState::up)
                {
                    ms = std::chrono::duration_cast<std::chrono::milliseconds>
                         (now - _last_click[button]).count();
                    _last_click[button] = now;

                    if (ms < CLICK_TIME_MS && button == MouseButton::left) {
                        _on_double_click();
                    } else {
                        _on_click[button]();
                    }
                }
            }

            _state[button] = state;
        }
        _last_update[button] = now;
    };

    void update_mouse_scroll(Int2 scroll) override {};

    void set_on_click(std::function<void()> on_click,
                      MouseButton button = MouseButton::left) {
        _on_click[button] = on_click;
    }

    void set_on_double_click(std::function<void()> on_click){
        _on_double_click = on_click;
    }

private:
    std::map<MouseButton, MouseState> _state;
    std::map<MouseButton, TimePoint> _last_update;
    std::map<MouseButton, TimePoint> _last_click;

    std::map<MouseButton, std::function<void()>> _on_click;
    std::function<void()> _on_double_click;

    const int CLICK_TIME_MS = 200;
};

class ControlBase : public virtual IVisualElement,
                    public MouseEventsHandler
{
public:
    ControlBase(const Size2& position,
                const Size2& size,
                const Margin& margin)
        : _position(position), _size(size), _margin(margin)
    {}

    Rect arrange(const Rect& origin) override
    {
        auto x0 = _position.x.to_pixels(origin.size.x) + _margin.left;
        auto y0 = _position.y.to_pixels(origin.size.y) + _margin.top;

        auto w = std::min(_size.x.to_pixels(origin.size.x),
                          origin.size.x - _margin.right - _margin.left);
        auto h = std::min(_size.y.to_pixels(origin.size.y),
                          origin.size.y - _margin.bottom - _margin.top);

        x0 += origin.position.x;
        y0 += origin.position.y;

        return { { x0, y0 }, { w, h } };
    }

    const Margin& get_margin() const override { return _margin; }
    const Size2& get_size() const override { return _size; }

private:
    Size2 _position;
    Size2 _size;
    Margin _margin;
};

class Button : public ControlBase
{
public:
    Button(const Size2& position,
           const Size2& size,
           const Margin& margin,
           const Color3& color)
        : ControlBase(position, size, margin), _color(color)
    {}

    void render(const Rect& origin) override
    {
        glBegin(GL_QUADS);
        glColor3f(_color.r, _color.g, _color.b);

        auto rect = arrange(origin);

        glVertex2i(rect.position.x, rect.position.y);
        glVertex2i(rect.position.x, rect.position.y + rect.size.y);
        glVertex2i(rect.position.x + rect.size.x,
                   rect.position.y + rect.size.y);
        glVertex2i(rect.position.x + rect.size.x,
                   rect.position.y);

        glEnd();
    }

private:
    Color3 _color;
};

enum class Orientation
{
    vertical,
    horizontal
};

class Container : public ControlBase
{
public:
    Container(const Size2& position,
              const Size2& size,
              const Margin& margin,
              Orientation orientation = Orientation::vertical)
        : ControlBase(position, size, margin), _orientation(orientation)
    {}

    void add_item(std::unique_ptr<IVisualElement> item)
    {
        _content.push_back(std::move(item));
    }

    void render(const Rect& origin) override
    {
        auto rect = arrange(origin);

        Size Size2::* field;
        int Int2::* ifield;
        if (_orientation == Orientation::vertical) {
            field = &Size2::y;
            ifield = &Int2::y;
        } else {
            field = &Size2::x;
            ifield = &Int2::x;
        }

        // first, scan items, map the "greedy" ones wanting relative portion
        std::vector<IVisualElement*> greedy;
        std::unordered_map<IVisualElement*, int> sizes;
        auto sum = 0;
        for (auto& p : _content) {
            auto p_rect = p->arrange(rect);
            auto p_total = p->get_margin().apply(p_rect);

            if ((p->get_size().*field).is_const()) {
                auto pixels = (p->get_size().*field).get_pixels();
                sum += pixels;
                sizes[p.get()] = pixels;
            } else {
                greedy.push_back(p.get());
            }
        }

        auto rest = std::max(rect.size.*ifield - sum, 0);
        float total_parts = 0;
        for (auto ptr : greedy) {
            total_parts += (ptr->get_size().*field).get_percents();
        }
        for (auto ptr : greedy) {
            auto f = ((ptr->get_size().*field).get_percents() / total_parts);
            sizes[ptr] = (int) (rest * f);
        }

        sum = rect.position.*ifield;
        for (auto& p : _content) {
            auto new_origin = rect;
            (new_origin.position.*ifield) = sum;
            (new_origin.size.*ifield) = sizes[p.get()];
            sum += sizes[p.get()];
            p->render(new_origin);
        }
    }

private:
    std::vector<std::unique_ptr<IVisualElement>> _content;
    Orientation _orientation;
};

int main(int argc, char * argv[]) try
{
    glfwInit();
    GLFWwindow * win = glfwCreateWindow(1280, 960, "main", 0, 0);
    glfwMakeContextCurrent(win);

    Color3 redish { 0.8f, 0.5f, 0.6f };

    Container c( { 0, 0 }, { 300, 1.0f }, { 5, 5, 5, 5 } );
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 1.0f }, { 5, 5, 5, 5 }, redish )));
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));
    c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));

    c.set_on_double_click([&](){
        c.add_item(std::unique_ptr<Button>(new Button( { 0, 0 }, { 1.0f, 35 }, { 5, 5, 5, 5 }, redish )));
    });

    glfwSetWindowUserPointer(win, &c);
    glfwSetCursorPosCallback(win, [](GLFWwindow * w, double x, double y) {
        auto ui_element = (IVisualElement*)glfwGetWindowUserPointer(w);
        ui_element->update_mouse_position({ (int)x, (int)y });
    });
    glfwSetScrollCallback(win, [](GLFWwindow * w, double x, double y) {
        auto ui_element = (IVisualElement*)glfwGetWindowUserPointer(w);
        ui_element->update_mouse_scroll({ (int)x, (int)y });
    });
    glfwSetMouseButtonCallback(win, [](GLFWwindow * w, int button, int action, int mods)
    {
        auto ui_element = (IVisualElement*)glfwGetWindowUserPointer(w);
        MouseButton button_type;
        switch(button)
        {
        case GLFW_MOUSE_BUTTON_RIGHT:
            button_type = MouseButton::right; break;
        case GLFW_MOUSE_BUTTON_LEFT:
            button_type = MouseButton::left; break;
        case GLFW_MOUSE_BUTTON_MIDDLE:
            button_type = MouseButton::middle; break;
        default:
            button_type = MouseButton::left;
        };

        MouseState mouse_state;
        switch(action)
        {
        case GLFW_PRESS:
            mouse_state = MouseState::down;
            break;
        case GLFW_RELEASE:
            mouse_state = MouseState::up;
            break;
        default:
            mouse_state = MouseState::up;
        };

        ui_element->update_mouse_state(button_type, mouse_state);
    });

    while (!glfwWindowShouldClose(win))
    {
        glfwPollEvents();

        int w,h;
        glfwGetFramebufferSize(win, &w, &h);
        glViewport(0, 0, w, h);
        glClear(GL_COLOR_BUFFER_BIT);

        glPushMatrix();
        glfwGetWindowSize(win, &w, &h);
        glOrtho(0, w, h, 0, -1, +1);

        Rect origin { { 0, 0 }, { w, h } };

        c.render(origin);

        glPopMatrix();
        glfwSwapBuffers(win);
    }

    glfwDestroyWindow(win);
    glfwTerminate();
    return 0;
}
catch(const std::exception & e)
{
    std::cerr << e.what() << std::endl;
    return -1;
}
<|endoftext|>