playing with constraint based layouting
This commit is contained in:
parent
bebdd80c9e
commit
35b98e4b69
|
@ -0,0 +1,256 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "AnchorBox.h"
|
||||||
|
|
||||||
|
#include "Solver.h"
|
||||||
|
#include "Constraint.h"
|
||||||
|
#include "Variable.h"
|
||||||
|
#include "Expression.h"
|
||||||
|
|
||||||
|
#include <QskLayoutConstraint.h>
|
||||||
|
#include <QskEvent.h>
|
||||||
|
#include <QskQuick.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
static inline Qt::Orientation qskOrientation( int edge )
|
||||||
|
{
|
||||||
|
return ( edge <= Qt::AnchorRight ) ? Qt::Horizontal : Qt::Vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Geometry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Expression expressionAt( int anchorPoint )
|
||||||
|
{
|
||||||
|
switch( anchorPoint )
|
||||||
|
{
|
||||||
|
case Qt::AnchorLeft:
|
||||||
|
return Term( left );
|
||||||
|
|
||||||
|
case Qt::AnchorHorizontalCenter:
|
||||||
|
return centerH();
|
||||||
|
|
||||||
|
case Qt::AnchorRight:
|
||||||
|
return Term( right );
|
||||||
|
|
||||||
|
case Qt::AnchorTop:
|
||||||
|
return Term( top );
|
||||||
|
|
||||||
|
case Qt::AnchorVerticalCenter:
|
||||||
|
return centerV();
|
||||||
|
|
||||||
|
case Qt::AnchorBottom:
|
||||||
|
return Term( bottom );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Expression();
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression length( Qt::Orientation orientation )
|
||||||
|
{
|
||||||
|
return ( orientation == Qt::Horizontal ) ? width() : height();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF rect() const
|
||||||
|
{
|
||||||
|
return QRectF( left.value(), top.value(),
|
||||||
|
right.value() - left.value(), bottom.value() - top.value() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression width() const { return right - left; }
|
||||||
|
Expression height() const { return bottom - top; }
|
||||||
|
|
||||||
|
Expression centerH() const { return left + 0.5 * width(); }
|
||||||
|
Expression centerV() const { return top + 0.5 * height(); }
|
||||||
|
|
||||||
|
Variable left, right, top, bottom;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Anchor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QQuickItem* item1 = nullptr;
|
||||||
|
Qt::AnchorPoint edge1;
|
||||||
|
|
||||||
|
QQuickItem* item2 = nullptr;
|
||||||
|
Qt::AnchorPoint edge2;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class AnchorBox::PrivateData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void setupSolver( int type, Solver& );
|
||||||
|
|
||||||
|
QMap< QQuickItem*, Geometry > geometries;
|
||||||
|
QVector< Anchor > anchors;
|
||||||
|
};
|
||||||
|
|
||||||
|
void AnchorBox::PrivateData::setupSolver( int type, Solver& solver )
|
||||||
|
{
|
||||||
|
for ( const auto& anchor : anchors )
|
||||||
|
{
|
||||||
|
auto& r1 = geometries[ anchor.item1 ];
|
||||||
|
auto& r2 = geometries[ anchor.item2 ];
|
||||||
|
|
||||||
|
solver.addConstraint( r1.expressionAt( anchor.edge1 )
|
||||||
|
== r2.expressionAt( anchor.edge2 ) );
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if ( type < 0 )
|
||||||
|
{
|
||||||
|
const auto s1 = 1.0;
|
||||||
|
const auto s2 = 1.0;
|
||||||
|
const auto o = qskOrientation( anchor.edge1 );
|
||||||
|
|
||||||
|
Constraint c( r1.length( o ) * s1 == r2.length( o ) * s2, Strength::medium );
|
||||||
|
solver.addConstraint( c );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
||||||
|
{
|
||||||
|
const auto item = it.key();
|
||||||
|
auto& r = it.value();
|
||||||
|
|
||||||
|
if ( type < 0 || type == Qt::MinimumSize )
|
||||||
|
{
|
||||||
|
const auto minSize = QskLayoutConstraint::sizeHint( item, Qt::MinimumSize );
|
||||||
|
solver.addConstraint( r.right >= r.left + minSize.width() );
|
||||||
|
solver.addConstraint( r.bottom >= r.top + minSize.height() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type < 0 || type == Qt::PreferredSize )
|
||||||
|
{
|
||||||
|
const auto prefSize = QskLayoutConstraint::sizeHint( item, Qt::PreferredSize );
|
||||||
|
|
||||||
|
Constraint c1( r.right == r.left + prefSize.width(), Strength::strong );
|
||||||
|
solver.addConstraint( c1 );
|
||||||
|
|
||||||
|
Constraint c2( r.bottom == r.top + prefSize.height(), Strength::strong );
|
||||||
|
solver.addConstraint( c2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( type < 0 || type == Qt::MaximumSize )
|
||||||
|
{
|
||||||
|
const auto maxSize = QskLayoutConstraint::sizeHint( item, Qt::MaximumSize );
|
||||||
|
if ( maxSize.width() < QskLayoutConstraint::unlimited )
|
||||||
|
solver.addConstraint( r.right <= r.left + maxSize.width() );
|
||||||
|
|
||||||
|
if ( maxSize.height() < QskLayoutConstraint::unlimited )
|
||||||
|
solver.addConstraint( r.bottom <= r.top + maxSize.height() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnchorBox::AnchorBox( QQuickItem* parent )
|
||||||
|
: QskControl( parent )
|
||||||
|
, m_data( new PrivateData )
|
||||||
|
{
|
||||||
|
(void)m_data->geometries[ this ];
|
||||||
|
}
|
||||||
|
|
||||||
|
AnchorBox::~AnchorBox()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::addAnchor( QQuickItem* item,
|
||||||
|
Qt::AnchorPoint edge1, Qt::AnchorPoint edge2 )
|
||||||
|
{
|
||||||
|
addAnchor( item, edge1, this, edge2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::addAnchor( QQuickItem* item1, Qt::AnchorPoint edge1,
|
||||||
|
QQuickItem* item2, Qt::AnchorPoint edge2 )
|
||||||
|
{
|
||||||
|
if ( item1 == item2 || item1 == nullptr || item2 == nullptr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( item1 != this )
|
||||||
|
{
|
||||||
|
if ( item1->parent() == nullptr )
|
||||||
|
item1->setParent( this );
|
||||||
|
|
||||||
|
if ( item1->parentItem() != this )
|
||||||
|
item1->setParentItem( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( item2 != this )
|
||||||
|
{
|
||||||
|
if ( item2->parent() == nullptr )
|
||||||
|
item2->setParent( this );
|
||||||
|
|
||||||
|
if ( item2->parentItem() != this )
|
||||||
|
item2->setParentItem( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)m_data->geometries[ item1 ];
|
||||||
|
(void)m_data->geometries[ item2 ];
|
||||||
|
|
||||||
|
Anchor anchor;
|
||||||
|
anchor.item1 = item1;
|
||||||
|
anchor.edge1 = edge1;
|
||||||
|
anchor.item2 = item2;
|
||||||
|
anchor.edge2 = edge2;
|
||||||
|
|
||||||
|
m_data->anchors += anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSizeF AnchorBox::boxHint( Qt::SizeHint which )
|
||||||
|
{
|
||||||
|
Solver solver;
|
||||||
|
m_data->setupSolver( which, solver );
|
||||||
|
solver.updateVariables();
|
||||||
|
|
||||||
|
auto& r0 = m_data->geometries[ this ];
|
||||||
|
|
||||||
|
return QSizeF( r0.rect().size() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::setItemGeometries( const QRectF& rect )
|
||||||
|
{
|
||||||
|
Solver solver;
|
||||||
|
m_data->setupSolver( -1, solver );
|
||||||
|
|
||||||
|
auto& r0 = m_data->geometries[ this ];
|
||||||
|
|
||||||
|
solver.addConstraint( r0.left == rect.left() );
|
||||||
|
solver.addConstraint( r0.right == rect.right() );
|
||||||
|
solver.addConstraint( r0.top == rect.top() );
|
||||||
|
solver.addConstraint( r0.bottom == rect.bottom() );
|
||||||
|
|
||||||
|
solver.updateVariables();
|
||||||
|
|
||||||
|
const auto& geometries = m_data->geometries;
|
||||||
|
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
||||||
|
qskSetItemGeometry( it.key(), it.value().rect() );
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
qDebug() << "=== Rect:" << rect;
|
||||||
|
for ( auto it = geometries.begin(); it != geometries.end(); ++it )
|
||||||
|
qDebug() << it.key()->objectName() << it.value().rect();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::geometryChangeEvent( QskGeometryChangeEvent* event )
|
||||||
|
{
|
||||||
|
Inherited::geometryChangeEvent( event );
|
||||||
|
|
||||||
|
if ( event->isResized() )
|
||||||
|
polish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnchorBox::updateLayout()
|
||||||
|
{
|
||||||
|
if ( !maybeUnresized() )
|
||||||
|
setItemGeometries( layoutRect() );
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "moc_AnchorBox.cpp"
|
|
@ -0,0 +1,38 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the QSkinny License, Version 1.0
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef ANCHOR_BOX_H
|
||||||
|
#define ANCHOR_BOX_H
|
||||||
|
|
||||||
|
#include "QskControl.h"
|
||||||
|
|
||||||
|
class AnchorBox : public QskControl
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
using Inherited = QskControl;
|
||||||
|
|
||||||
|
public:
|
||||||
|
AnchorBox( QQuickItem* parent = nullptr );
|
||||||
|
~AnchorBox() override;
|
||||||
|
|
||||||
|
void addAnchor( QQuickItem*, Qt::AnchorPoint, Qt::AnchorPoint );
|
||||||
|
void addAnchor( QQuickItem*, Qt::AnchorPoint, QQuickItem*, Qt::AnchorPoint );
|
||||||
|
|
||||||
|
QSizeF boxHint( Qt::SizeHint );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void geometryChangeEvent( QskGeometryChangeEvent* ) override;
|
||||||
|
void updateLayout() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setItemGeometries( const QRectF& );
|
||||||
|
|
||||||
|
class PrivateData;
|
||||||
|
std::unique_ptr< PrivateData > m_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,285 @@
|
||||||
|
#include "Constraint.h"
|
||||||
|
#include "Expression.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
static Expression reduce( const Expression& expr )
|
||||||
|
{
|
||||||
|
std::map< Variable, double > vars;
|
||||||
|
|
||||||
|
for ( auto term : expr.terms() )
|
||||||
|
vars[ term.variable() ] += term.coefficient();
|
||||||
|
|
||||||
|
const std::vector< Term > terms( vars.begin(), vars.end() );
|
||||||
|
return Expression( terms, expr.constant() );
|
||||||
|
}
|
||||||
|
|
||||||
|
class Constraint::Data
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Data( const Expression& expr, RelationalOperator op, double strength )
|
||||||
|
: expression( reduce( expr ) )
|
||||||
|
, strength( Strength::clip( strength ) )
|
||||||
|
, op( op )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression expression;
|
||||||
|
double strength;
|
||||||
|
RelationalOperator op;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Constraint::Constraint( const Expression& expr, RelationalOperator op, double strength )
|
||||||
|
: m_data( std::make_shared< Data >( expr, op, strength ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint::Constraint( const Constraint& other, double strength )
|
||||||
|
: Constraint( other.expression(), other.oper(), strength )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint::~Constraint()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const Expression& Constraint::expression() const
|
||||||
|
{
|
||||||
|
return m_data->expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
RelationalOperator Constraint::oper() const
|
||||||
|
{
|
||||||
|
return m_data->op;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Constraint::strength() const
|
||||||
|
{
|
||||||
|
return m_data->strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Expression& first, const Expression& second )
|
||||||
|
{
|
||||||
|
return Constraint( first - second, OP_EQ );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Expression& expression, const Term& term )
|
||||||
|
{
|
||||||
|
return expression == Expression( term );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Expression& expression, const Variable& variable )
|
||||||
|
{
|
||||||
|
return expression == Term( variable );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Expression& expression, double constant )
|
||||||
|
{
|
||||||
|
return expression == Expression( constant );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Expression& first, const Expression& second )
|
||||||
|
{
|
||||||
|
return Constraint( first - second, OP_LE );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Expression& expression, const Term& term )
|
||||||
|
{
|
||||||
|
return expression <= Expression( term );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Expression& expression, const Variable& variable )
|
||||||
|
{
|
||||||
|
return expression <= Term( variable );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Expression& expression, double constant )
|
||||||
|
{
|
||||||
|
return expression <= Expression( constant );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Expression& first, const Expression& second )
|
||||||
|
{
|
||||||
|
return Constraint( first - second, OP_GE );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Expression& expression, const Term& term )
|
||||||
|
{
|
||||||
|
return expression >= Expression( term );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Expression& expression, const Variable& variable )
|
||||||
|
{
|
||||||
|
return expression >= Term( variable );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Expression& expression, double constant )
|
||||||
|
{
|
||||||
|
return expression >= Expression( constant );
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Term& term, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression == term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Term& first, const Term& second )
|
||||||
|
{
|
||||||
|
return Expression( first ) == second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Term& term, const Variable& variable )
|
||||||
|
{
|
||||||
|
return Expression( term ) == variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Term& term, double constant )
|
||||||
|
{
|
||||||
|
return Expression( term ) == constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Term& term, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression >= term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Term& first, const Term& second )
|
||||||
|
{
|
||||||
|
return Expression( first ) <= second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Term& term, const Variable& variable )
|
||||||
|
{
|
||||||
|
return Expression( term ) <= variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Term& term, double constant )
|
||||||
|
{
|
||||||
|
return Expression( term ) <= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Term& term, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression <= term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Term& first, const Term& second )
|
||||||
|
{
|
||||||
|
return Expression( first ) >= second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Term& term, const Variable& variable )
|
||||||
|
{
|
||||||
|
return Expression( term ) >= variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Term& term, double constant )
|
||||||
|
{
|
||||||
|
return Expression( term ) >= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Variable& variable, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression == variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Variable& variable, const Term& term )
|
||||||
|
{
|
||||||
|
return term == variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Variable& first, const Variable& second )
|
||||||
|
{
|
||||||
|
return Term( first ) == second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( const Variable& variable, double constant )
|
||||||
|
{
|
||||||
|
return Term( variable ) == constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Variable& variable, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression >= variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Variable& variable, const Term& term )
|
||||||
|
{
|
||||||
|
return term >= variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Variable& first, const Variable& second )
|
||||||
|
{
|
||||||
|
return Term( first ) <= second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( const Variable& variable, double constant )
|
||||||
|
{
|
||||||
|
return Term( variable ) <= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Variable& variable, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression <= variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Variable& variable, const Term& term )
|
||||||
|
{
|
||||||
|
return term <= variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Variable& first, const Variable& second )
|
||||||
|
{
|
||||||
|
return Term( first ) >= second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( const Variable& variable, double constant )
|
||||||
|
{
|
||||||
|
return Term( variable ) >= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( double constant, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression == constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( double constant, const Term& term )
|
||||||
|
{
|
||||||
|
return term == constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator==( double constant, const Variable& variable )
|
||||||
|
{
|
||||||
|
return variable == constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( double constant, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression >= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( double constant, const Term& term )
|
||||||
|
{
|
||||||
|
return term >= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator<=( double constant, const Variable& variable )
|
||||||
|
{
|
||||||
|
return variable >= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( double constant, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression <= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( double constant, const Term& term )
|
||||||
|
{
|
||||||
|
return term <= constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constraint operator>=( double constant, const Variable& variable )
|
||||||
|
{
|
||||||
|
return variable <= constant;
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Strength.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Expression;
|
||||||
|
class Variable;
|
||||||
|
class Term;
|
||||||
|
|
||||||
|
enum RelationalOperator { OP_LE, OP_GE, OP_EQ };
|
||||||
|
|
||||||
|
class Constraint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Constraint() = default;
|
||||||
|
|
||||||
|
Constraint( const Expression&, RelationalOperator,
|
||||||
|
double strength = Strength::required );
|
||||||
|
|
||||||
|
Constraint( const Constraint&, double strength );
|
||||||
|
|
||||||
|
~Constraint();
|
||||||
|
|
||||||
|
const Expression& expression() const;
|
||||||
|
RelationalOperator oper() const;
|
||||||
|
double strength() const;
|
||||||
|
|
||||||
|
bool operator!() const { return !m_data; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Data;
|
||||||
|
std::shared_ptr< Data > m_data;
|
||||||
|
|
||||||
|
friend bool operator<( const Constraint&, const Constraint& );
|
||||||
|
friend bool operator==( const Constraint&, const Constraint& );
|
||||||
|
friend bool operator!=( const Constraint&, const Constraint& );
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator<( const Constraint& lhs, const Constraint& rhs )
|
||||||
|
{
|
||||||
|
return lhs.m_data < rhs.m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==( const Constraint& lhs, const Constraint& rhs )
|
||||||
|
{
|
||||||
|
return lhs.m_data == rhs.m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=( const Constraint& lhs, const Constraint& rhs )
|
||||||
|
{
|
||||||
|
return lhs.m_data != rhs.m_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Constraint operator|( const Constraint& constraint, double strength )
|
||||||
|
{
|
||||||
|
return Constraint( constraint, strength );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Constraint operator|( double strength, const Constraint& constraint )
|
||||||
|
{
|
||||||
|
return constraint | strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern Constraint operator==( const Expression&, const Expression& );
|
||||||
|
extern Constraint operator<=( const Expression&, const Expression& );
|
||||||
|
extern Constraint operator>=( const Expression&, const Expression& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Expression&, const Term& );
|
||||||
|
extern Constraint operator<=( const Expression&, const Term& );
|
||||||
|
extern Constraint operator>=( const Expression&, const Term& );
|
||||||
|
extern Constraint operator==( const Term&, const Expression& );
|
||||||
|
extern Constraint operator<=( const Term&, const Expression& );
|
||||||
|
extern Constraint operator>=( const Term&, const Expression& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Expression&, const Variable& );
|
||||||
|
extern Constraint operator<=( const Expression&, const Variable& );
|
||||||
|
extern Constraint operator>=( const Expression&, const Variable& );
|
||||||
|
extern Constraint operator==( const Variable&, const Expression& );
|
||||||
|
extern Constraint operator<=( const Variable&, const Expression& );
|
||||||
|
extern Constraint operator>=( const Variable&, const Expression& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Expression&, double );
|
||||||
|
extern Constraint operator<=( const Expression&, double );
|
||||||
|
extern Constraint operator>=( const Expression&, double );
|
||||||
|
extern Constraint operator==( double, const Expression& );
|
||||||
|
extern Constraint operator<=( double, const Expression& );
|
||||||
|
extern Constraint operator>=( double, const Expression& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Term&, const Term& );
|
||||||
|
extern Constraint operator<=( const Term&, const Term& );
|
||||||
|
extern Constraint operator>=( const Term&, const Term& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Term&, const Variable& );
|
||||||
|
extern Constraint operator<=( const Term&, const Variable& );
|
||||||
|
extern Constraint operator>=( const Term&, const Variable& );
|
||||||
|
extern Constraint operator==( const Variable&, const Term& );
|
||||||
|
extern Constraint operator<=( const Variable&, const Term& );
|
||||||
|
extern Constraint operator>=( const Variable&, const Term& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Term&, double );
|
||||||
|
extern Constraint operator<=( const Term&, double );
|
||||||
|
extern Constraint operator>=( const Term&, double );
|
||||||
|
extern Constraint operator==( double, const Term& );
|
||||||
|
extern Constraint operator<=( double, const Term& );
|
||||||
|
extern Constraint operator>=( double, const Term& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Variable&, const Variable& );
|
||||||
|
extern Constraint operator<=( const Variable&, const Variable& );
|
||||||
|
extern Constraint operator>=( const Variable&, const Variable& );
|
||||||
|
|
||||||
|
extern Constraint operator==( const Variable&, double );
|
||||||
|
extern Constraint operator<=( const Variable&, double );
|
||||||
|
extern Constraint operator>=( const Variable&, double );
|
||||||
|
extern Constraint operator==( double, const Variable& );
|
||||||
|
extern Constraint operator<=( double, const Variable& );
|
||||||
|
extern Constraint operator>=( double, const Variable& );
|
|
@ -0,0 +1,226 @@
|
||||||
|
#include "Expression.h"
|
||||||
|
#include "Term.h"
|
||||||
|
|
||||||
|
Expression::Expression( double constant )
|
||||||
|
: m_constant( constant )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression::Expression( const Term& term, double constant )
|
||||||
|
: m_terms( 1, term )
|
||||||
|
, m_constant( constant )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression::Expression( const std::vector< Term >&& terms, double constant )
|
||||||
|
: m_terms( std::move( terms ) )
|
||||||
|
, m_constant( constant )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression::Expression( const std::vector< Term >& terms, double constant )
|
||||||
|
: m_terms( terms )
|
||||||
|
, m_constant( constant )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
double Expression::value() const
|
||||||
|
{
|
||||||
|
double result = m_constant;
|
||||||
|
|
||||||
|
for ( const auto& term : m_terms )
|
||||||
|
result += term.value();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator*( const Expression& expression, double coefficient )
|
||||||
|
{
|
||||||
|
std::vector< Term > terms;
|
||||||
|
terms.reserve( expression.terms().size() );
|
||||||
|
|
||||||
|
for ( const auto& term : expression.terms() )
|
||||||
|
terms.push_back( term * coefficient );
|
||||||
|
|
||||||
|
return Expression( std::move( terms ), expression.constant() * coefficient );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator/( const Expression& expression, double denominator )
|
||||||
|
{
|
||||||
|
return expression * ( 1.0 / denominator );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression * -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator*( double coefficient, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression * coefficient;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Expression& first, const Expression& second )
|
||||||
|
{
|
||||||
|
std::vector< Term > terms;
|
||||||
|
terms.reserve( first.terms().size() + second.terms().size() );
|
||||||
|
terms.insert( terms.begin(), first.terms().begin(), first.terms().end() );
|
||||||
|
terms.insert( terms.end(), second.terms().begin(), second.terms().end() );
|
||||||
|
|
||||||
|
return Expression( std::move( terms ), first.constant() + second.constant() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Expression& expression, const Term& term )
|
||||||
|
{
|
||||||
|
std::vector< Term > terms;
|
||||||
|
terms.reserve( expression.terms().size() + 1 );
|
||||||
|
terms.insert( terms.begin(), expression.terms().begin(), expression.terms().end() );
|
||||||
|
terms.push_back( term );
|
||||||
|
|
||||||
|
return Expression( std::move( terms ), expression.constant() );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Expression& expression, const Variable& variable )
|
||||||
|
{
|
||||||
|
return expression + Term( variable );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Expression& expression, double constant )
|
||||||
|
{
|
||||||
|
return Expression( expression.terms(), expression.constant() + constant );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Expression& first, const Expression& second )
|
||||||
|
{
|
||||||
|
return first + -second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Expression& expression, const Term& term )
|
||||||
|
{
|
||||||
|
return expression + -term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Expression& expression, const Variable& variable )
|
||||||
|
{
|
||||||
|
return expression + -variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Expression& expression, double constant )
|
||||||
|
{
|
||||||
|
return expression + -constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Term& term, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression + term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Term& first, const Term& second )
|
||||||
|
{
|
||||||
|
std::vector< Term > terms;
|
||||||
|
terms.reserve( 2 );
|
||||||
|
terms.push_back( first );
|
||||||
|
terms.push_back( second );
|
||||||
|
|
||||||
|
return Expression( std::move( terms ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Term& term, const Variable& variable )
|
||||||
|
{
|
||||||
|
return term + Term( variable );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Term& term, double constant )
|
||||||
|
{
|
||||||
|
return Expression( term, constant );
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Term& term, const Expression& expression )
|
||||||
|
{
|
||||||
|
return -expression + term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Term& first, const Term& second )
|
||||||
|
{
|
||||||
|
return first + -second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Term& term, const Variable& variable )
|
||||||
|
{
|
||||||
|
return term + -variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Term& term, double constant )
|
||||||
|
{
|
||||||
|
return term + -constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Variable& variable, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression + variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Variable& variable, const Term& term )
|
||||||
|
{
|
||||||
|
return term + variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Variable& first, const Variable& second )
|
||||||
|
{
|
||||||
|
return Term( first ) + second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( const Variable& variable, double constant )
|
||||||
|
{
|
||||||
|
return Term( variable ) + constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Variable& variable, const Expression& expression )
|
||||||
|
{
|
||||||
|
return variable + -expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Variable& variable, const Term& term )
|
||||||
|
{
|
||||||
|
return variable + -term;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Variable& first, const Variable& second )
|
||||||
|
{
|
||||||
|
return first + -second;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( const Variable& variable, double constant )
|
||||||
|
{
|
||||||
|
return variable + -constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( double constant, const Expression& expression )
|
||||||
|
{
|
||||||
|
return expression + constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( double constant, const Term& term )
|
||||||
|
{
|
||||||
|
return term + constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator+( double constant, const Variable& variable )
|
||||||
|
{
|
||||||
|
return variable + constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( double constant, const Expression& expression )
|
||||||
|
{
|
||||||
|
return -expression + constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( double constant, const Term& term )
|
||||||
|
{
|
||||||
|
return -term + constant;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression operator-( double constant, const Variable& variable )
|
||||||
|
{
|
||||||
|
return -variable + constant;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "Term.h"
|
||||||
|
|
||||||
|
class Expression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Expression( double constant = 0.0 );
|
||||||
|
Expression( const Term&, double constant = 0.0 );
|
||||||
|
|
||||||
|
Expression( const std::vector< Term >&, double constant = 0.0 );
|
||||||
|
Expression( const std::vector< Term >&&, double constant = 0.0 );
|
||||||
|
|
||||||
|
const std::vector< Term >& terms() const { return m_terms; }
|
||||||
|
double constant() const { return m_constant; }
|
||||||
|
|
||||||
|
double value() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector< Term > m_terms;
|
||||||
|
double m_constant;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Expression operator-( const Expression& );
|
||||||
|
|
||||||
|
extern Expression operator+( const Expression&, const Expression& );
|
||||||
|
extern Expression operator-( const Expression&, const Expression& );
|
||||||
|
|
||||||
|
extern Expression operator+( const Expression&, const Term& );
|
||||||
|
extern Expression operator-( const Expression&, const Term& );
|
||||||
|
extern Expression operator+( const Term&, const Expression&);
|
||||||
|
extern Expression operator-( const Term&, const Expression&);
|
||||||
|
|
||||||
|
extern Expression operator+( const Expression&, const Variable& );
|
||||||
|
extern Expression operator-( const Expression&, const Variable& );
|
||||||
|
extern Expression operator-( const Variable&, const Expression&);
|
||||||
|
extern Expression operator+( const Variable&, const Expression&);
|
||||||
|
|
||||||
|
extern Expression operator*( const Expression&, double );
|
||||||
|
extern Expression operator/( const Expression&, double );
|
||||||
|
extern Expression operator+( const Expression&, double );
|
||||||
|
extern Expression operator-( const Expression&, double );
|
||||||
|
extern Expression operator*( double, const Expression&);
|
||||||
|
extern Expression operator+( double, const Expression&);
|
||||||
|
extern Expression operator-( double, const Expression&);
|
||||||
|
|
||||||
|
extern Expression operator+( const Term&, const Term& );
|
||||||
|
extern Expression operator-( const Term&, const Term& );
|
||||||
|
|
||||||
|
extern Expression operator+( const Term&, const Variable& );
|
||||||
|
extern Expression operator-( const Term&, const Variable& );
|
||||||
|
extern Expression operator-( const Variable&, const Term&);
|
||||||
|
extern Expression operator+( const Variable&, const Term&);
|
||||||
|
|
||||||
|
extern Expression operator+( const Term&, double );
|
||||||
|
extern Expression operator-( const Term&, double );
|
||||||
|
extern Expression operator+( double, const Term&);
|
||||||
|
extern Expression operator-( double, const Term&);
|
||||||
|
|
||||||
|
extern Expression operator+( const Variable&, const Variable& );
|
||||||
|
extern Expression operator-( const Variable&, const Variable& );
|
||||||
|
|
||||||
|
extern Expression operator+( const Variable&, double );
|
||||||
|
extern Expression operator-( const Variable&, double );
|
||||||
|
extern Expression operator+( double, const Variable& );
|
||||||
|
extern Expression operator-( double, const Variable& );
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <qglobal.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Variable;
|
||||||
|
class Constraint;
|
||||||
|
class SimplexSolver;
|
||||||
|
|
||||||
|
class Solver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Solver();
|
||||||
|
~Solver();
|
||||||
|
|
||||||
|
void addConstraint( const Constraint& );
|
||||||
|
void removeConstraint( const Constraint& );
|
||||||
|
bool hasConstraint( const Constraint& ) const;
|
||||||
|
|
||||||
|
void addEditVariable( const Variable&, double strength );
|
||||||
|
void removeEditVariable( const Variable& );
|
||||||
|
|
||||||
|
bool hasEditVariable( const Variable& ) const;
|
||||||
|
void suggestValue( const Variable&, double value );
|
||||||
|
|
||||||
|
void updateVariables();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY( Solver )
|
||||||
|
std::unique_ptr< SimplexSolver > m_solver;
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace Strength
|
||||||
|
{
|
||||||
|
inline double create( double a, double b, double c, double w = 1.0 )
|
||||||
|
{
|
||||||
|
double result = 0.0;
|
||||||
|
result += std::max( 0.0, std::min( 1000.0, a * w ) ) * 1000000.0;
|
||||||
|
result += std::max( 0.0, std::min( 1000.0, b * w ) ) * 1000.0;
|
||||||
|
result += std::max( 0.0, std::min( 1000.0, c * w ) );
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const double required = create( 1000.0, 1000.0, 1000.0 );
|
||||||
|
const double strong = create( 1.0, 0.0, 0.0 );
|
||||||
|
const double medium = create( 0.0, 1.0, 0.0 );
|
||||||
|
const double weak = create( 0.0, 0.0, 1.0 );
|
||||||
|
|
||||||
|
inline double clip( double value )
|
||||||
|
{
|
||||||
|
return std::max( 0.0, std::min( required, value ) );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include "Variable.h"
|
||||||
|
|
||||||
|
class Term
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
Term( const Variable& variable, double coefficient = 1.0 )
|
||||||
|
: m_variable( variable )
|
||||||
|
, m_coefficient( coefficient )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// to facilitate efficient map -> vector copies
|
||||||
|
Term( const std::pair< const Variable, double >& pair )
|
||||||
|
: m_variable( pair.first )
|
||||||
|
, m_coefficient( pair.second )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const Variable& variable() const
|
||||||
|
{
|
||||||
|
return m_variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
double coefficient() const
|
||||||
|
{
|
||||||
|
return m_coefficient;
|
||||||
|
}
|
||||||
|
|
||||||
|
double value() const
|
||||||
|
{
|
||||||
|
return m_coefficient * m_variable.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Variable m_variable;
|
||||||
|
double m_coefficient;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline Term operator*( const Variable& variable, double coefficient )
|
||||||
|
{
|
||||||
|
return Term( variable, coefficient );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator/( const Variable& variable, double denominator )
|
||||||
|
{
|
||||||
|
return variable * ( 1.0 / denominator );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator-( const Variable& variable )
|
||||||
|
{
|
||||||
|
return variable * -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator*( const Term& term, double coefficient )
|
||||||
|
{
|
||||||
|
return Term( term.variable(), term.coefficient() * coefficient );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator/( const Term& term, double denominator )
|
||||||
|
{
|
||||||
|
return term * ( 1.0 / denominator );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator-( const Term& term )
|
||||||
|
{
|
||||||
|
return term * -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator*( double coefficient, const Term& term )
|
||||||
|
{
|
||||||
|
return term * coefficient;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Term operator*( double coefficient, const Variable& variable )
|
||||||
|
{
|
||||||
|
return variable * coefficient;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
class Variable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Variable( double value = 0.0 )
|
||||||
|
: m_value( std::make_shared< double >(value) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable( const Variable& v )
|
||||||
|
: m_value( v.m_value )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Variable& operator=( const Variable& v )
|
||||||
|
{
|
||||||
|
m_value = v.m_value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
double value() const
|
||||||
|
{
|
||||||
|
return m_value ? *m_value : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(double x)
|
||||||
|
{
|
||||||
|
*m_value = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool equals( const Variable& other )
|
||||||
|
{
|
||||||
|
return m_value == other.m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr< double > m_value;
|
||||||
|
|
||||||
|
friend bool operator<( const Variable& lhs, const Variable& rhs )
|
||||||
|
{
|
||||||
|
return lhs.m_value < rhs.m_value;
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,21 @@
|
||||||
|
CONFIG += qskexample
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
Constraint.h \
|
||||||
|
Expression.h \
|
||||||
|
Solver.h \
|
||||||
|
Strength.h \
|
||||||
|
Term.h \
|
||||||
|
Variable.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
Expression.cpp \
|
||||||
|
Constraint.cpp \
|
||||||
|
Solver.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
AnchorBox.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
AnchorBox.cpp \
|
||||||
|
main.cpp
|
|
@ -0,0 +1,190 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* QSkinny - Copyright (C) 2016 Uwe Rathmann
|
||||||
|
* This file may be used under the terms of the 3-clause BSD License
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#include "AnchorBox.h"
|
||||||
|
|
||||||
|
#include <SkinnyFont.h>
|
||||||
|
#include <SkinnyShortcut.h>
|
||||||
|
|
||||||
|
#include <QskControl.h>
|
||||||
|
#include <QskObjectCounter.h>
|
||||||
|
#include <QskWindow.h>
|
||||||
|
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class Rectangle : public QskControl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Rectangle( const char* colorName, QQuickItem* parent = nullptr )
|
||||||
|
: QskControl( parent)
|
||||||
|
, m_colorName( colorName )
|
||||||
|
{
|
||||||
|
setObjectName( colorName );
|
||||||
|
|
||||||
|
initSizePolicy( QskSizePolicy::Preferred, QskSizePolicy::Preferred );
|
||||||
|
|
||||||
|
setMinimumSize( 10, 10 );
|
||||||
|
setPreferredSize( 100, 100 );
|
||||||
|
setMaximumSize( 1000, 1000 );
|
||||||
|
|
||||||
|
setBackgroundColor( colorName );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void geometryChangeEvent( QskGeometryChangeEvent* event ) override
|
||||||
|
{
|
||||||
|
QskControl::geometryChangeEvent( event );
|
||||||
|
#if 0
|
||||||
|
qDebug() << m_colorName << size();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray m_colorName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class MyBox : public AnchorBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MyBox( QQuickItem* parent = nullptr )
|
||||||
|
: AnchorBox( parent )
|
||||||
|
{
|
||||||
|
setObjectName( "Box" );
|
||||||
|
|
||||||
|
setup1();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup1();
|
||||||
|
void setup2();
|
||||||
|
void setup3();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void geometryChangeEvent( QskGeometryChangeEvent* event ) override
|
||||||
|
{
|
||||||
|
AnchorBox::geometryChangeEvent( event );
|
||||||
|
#if 1
|
||||||
|
qDebug() << boxHint( Qt::MinimumSize );
|
||||||
|
qDebug() << boxHint( Qt::PreferredSize );
|
||||||
|
qDebug() << boxHint( Qt::MaximumSize );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void MyBox::setup1()
|
||||||
|
{
|
||||||
|
auto a = new Rectangle( "PaleVioletRed" );
|
||||||
|
auto b = new Rectangle( "DarkSeaGreen" );
|
||||||
|
auto c = new Rectangle( "SkyBlue" );
|
||||||
|
auto d = new Rectangle( "Coral" );
|
||||||
|
auto e = new Rectangle( "NavajoWhite" );
|
||||||
|
auto f = new Rectangle( "Peru" );
|
||||||
|
auto g = new Rectangle( "Olive" );
|
||||||
|
|
||||||
|
addAnchor( a, Qt::AnchorTop, Qt::AnchorTop );
|
||||||
|
addAnchor( b, Qt::AnchorTop, Qt::AnchorTop );
|
||||||
|
|
||||||
|
addAnchor( c, Qt::AnchorTop, a, Qt::AnchorBottom );
|
||||||
|
addAnchor( c, Qt::AnchorTop, b, Qt::AnchorBottom );
|
||||||
|
addAnchor( c, Qt::AnchorBottom, d, Qt::AnchorTop );
|
||||||
|
addAnchor( c, Qt::AnchorBottom, e, Qt::AnchorTop );
|
||||||
|
|
||||||
|
addAnchor( d, Qt::AnchorBottom, Qt::AnchorBottom );
|
||||||
|
addAnchor( e, Qt::AnchorBottom, Qt::AnchorBottom );
|
||||||
|
|
||||||
|
addAnchor( c, Qt::AnchorTop, f, Qt::AnchorTop );
|
||||||
|
addAnchor( c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom );
|
||||||
|
addAnchor( f, Qt::AnchorBottom, g, Qt::AnchorTop );
|
||||||
|
addAnchor( c, Qt::AnchorBottom, g, Qt::AnchorBottom );
|
||||||
|
|
||||||
|
// horizontal
|
||||||
|
addAnchor( a, Qt::AnchorLeft, Qt::AnchorLeft );
|
||||||
|
addAnchor( d, Qt::AnchorLeft, Qt::AnchorLeft );
|
||||||
|
addAnchor( a, Qt::AnchorRight, b, Qt::AnchorLeft );
|
||||||
|
|
||||||
|
addAnchor( a, Qt::AnchorRight, c, Qt::AnchorLeft );
|
||||||
|
addAnchor( c, Qt::AnchorRight, e, Qt::AnchorLeft );
|
||||||
|
|
||||||
|
addAnchor( b, Qt::AnchorRight, Qt::AnchorRight );
|
||||||
|
addAnchor( e, Qt::AnchorRight, Qt::AnchorRight );
|
||||||
|
addAnchor( d, Qt::AnchorRight, e, Qt::AnchorLeft );
|
||||||
|
|
||||||
|
addAnchor( f, Qt::AnchorLeft, Qt::AnchorLeft );
|
||||||
|
addAnchor( g, Qt::AnchorLeft, Qt::AnchorLeft );
|
||||||
|
addAnchor( f, Qt::AnchorRight, g, Qt::AnchorRight );
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyBox::setup2()
|
||||||
|
{
|
||||||
|
auto a = new Rectangle( "PaleVioletRed" );
|
||||||
|
|
||||||
|
addAnchor( a, Qt::AnchorLeft, Qt::AnchorLeft );
|
||||||
|
addAnchor( a, Qt::AnchorTop, Qt::AnchorTop );
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
auto b = new Rectangle( "DarkSeaGreen" );
|
||||||
|
addAnchor( a, Qt::AnchorRight, b, Qt::AnchorLeft );
|
||||||
|
addAnchor( b, Qt::AnchorRight, m_layout, Qt::AnchorRight );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
auto c = new Rectangle( "SkyBlue" );
|
||||||
|
addAnchor( a, Qt::AnchorBottom, c, Qt::AnchorTop );
|
||||||
|
addAnchor( a, Qt::AnchorRight, c, Qt::AnchorRight );
|
||||||
|
|
||||||
|
auto d = new Rectangle( "Coral" );
|
||||||
|
addAnchor( c, Qt::AnchorLeft, d, Qt::AnchorLeft );
|
||||||
|
addAnchor( c, Qt::AnchorBottom, d, Qt::AnchorTop );
|
||||||
|
addAnchor( d, Qt::AnchorRight, Qt::AnchorRight );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyBox::setup3()
|
||||||
|
{
|
||||||
|
auto a = new Rectangle( "PaleVioletRed" );
|
||||||
|
auto b = new Rectangle( "DarkSeaGreen" );
|
||||||
|
auto c = new Rectangle( "SkyBlue" );
|
||||||
|
auto d = new Rectangle( "Coral" );
|
||||||
|
|
||||||
|
addAnchor( a, Qt::AnchorTop, Qt::AnchorTop );
|
||||||
|
|
||||||
|
addAnchor( a, Qt::AnchorLeft, Qt::AnchorLeft );
|
||||||
|
addAnchor( a, Qt::AnchorRight, b, Qt::AnchorLeft );
|
||||||
|
addAnchor( b, Qt::AnchorRight, c, Qt::AnchorLeft );
|
||||||
|
addAnchor( c, Qt::AnchorRight, d, Qt::AnchorLeft );
|
||||||
|
addAnchor( d, Qt::AnchorRight, Qt::AnchorRight );
|
||||||
|
|
||||||
|
auto e = new Rectangle( "NavajoWhite" );
|
||||||
|
#if 1
|
||||||
|
e->setMinimumWidth( 100 );
|
||||||
|
#endif
|
||||||
|
addAnchor( a, Qt::AnchorBottom, e, Qt::AnchorTop );
|
||||||
|
addAnchor( c, Qt::AnchorRight, e, Qt::AnchorRight );
|
||||||
|
addAnchor( b, Qt::AnchorLeft, e, Qt::AnchorLeft );
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( int argc, char* argv[] )
|
||||||
|
{
|
||||||
|
#ifdef ITEM_STATISTICS
|
||||||
|
QskObjectCounter counter( true );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QGuiApplication app( argc, argv );
|
||||||
|
|
||||||
|
SkinnyFont::init( &app );
|
||||||
|
SkinnyShortcut::enable( SkinnyShortcut::Quit | SkinnyShortcut::DebugShortcuts );
|
||||||
|
|
||||||
|
auto box = new MyBox();
|
||||||
|
|
||||||
|
QskWindow window;
|
||||||
|
window.addItem( box );
|
||||||
|
window.resize( 600, 600 );
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
TEMPLATE = subdirs
|
TEMPLATE = subdirs
|
||||||
|
|
||||||
SUBDIRS += \
|
SUBDIRS += \
|
||||||
|
anchors \
|
||||||
dialogbuttons \
|
dialogbuttons \
|
||||||
invoker \
|
invoker \
|
||||||
inputpanel \
|
inputpanel \
|
||||||
|
|
Loading…
Reference in New Issue