libs-gui/Source/GSCSConstraint.m

367 lines
No EOL
12 KiB
Objective-C

/* Copyright (C) 2023 Free Software Foundation, Inc.
By: Benjamin Johnson
Date: 19-3-2023
This file is part of the GNUstep Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110 USA.
*/
#import "GSCSConstraint.h"
#import "GSCSFloatComparator.h"
#import "GSCSVariable.h"
@implementation GSCSConstraint
- (instancetype) init
{
return [self initWithType: GSCSConstraintTypeLinear
strength: nil
expression: nil
variable: nil];
}
- (instancetype) initWithType: (GSCSConstraintType)type
strength: (GSCSStrength *)strength
expression: (GSCSLinearExpression *)expression
variable: (GSCSVariable *)variable
{
self = [super init];
if (self)
{
ASSIGN(_strength, strength != nil ? [strength copy]
: [GSCSStrength strengthRequired]);
ASSIGN(_expression, expression);
ASSIGN(_variable, variable);
_type = type;
}
return self;
}
- (instancetype) initLinearConstraintWithExpression:
(GSCSLinearExpression *)expression
strength: (GSCSStrength *)strength
variable: (GSCSVariable *)variable
{
return [self initWithType: GSCSConstraintTypeLinear
strength: strength
expression: expression
variable: variable];
}
- (instancetype) initLinearConstraintWithExpression:
(GSCSLinearExpression *)expression
{
return
[self initLinearConstraintWithExpression: expression
strength: [GSCSStrength strengthRequired]
variable: nil];
}
- (instancetype) initLinearInequityConstraintWithExpression:
(GSCSLinearExpression *)expression
{
return
[self initWithType: GSCSConstraintTypeLinearInequity
strength: [GSCSStrength strengthRequired]
expression: expression
variable: nil];
}
- (instancetype) initEditConstraintWithVariable: (GSCSVariable *)variable
strength: (GSCSStrength *)strength
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: variable
coefficient: -1
constant: [variable value]];
GSCSConstraint *constraint = [self initWithType: GSCSConstraintTypeEdit
strength: strength
expression: expression
variable: variable];
RELEASE(expression);
return constraint;
}
- (instancetype) initStayConstraintWithVariable: (GSCSVariable *)variable
strength: (GSCSStrength *)strength
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: variable
coefficient: -1
constant: [variable value]];
GSCSConstraint *constraint = [[GSCSConstraint alloc] initWithType: GSCSConstraintTypeStay
strength: strength
expression: expression
variable: variable];
RELEASE(expression);
return constraint;
}
- (instancetype) initWithLhsVariable: (GSCSVariable *)lhs
equalsRhsVariable: (GSCSVariable *)rhs
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: lhs];
[expression addVariable: rhs coefficient: -1];
GSCSConstraint *constraint = [self initLinearConstraintWithExpression: expression];
RELEASE(expression);
return constraint;
}
- (instancetype) initWithLhsVariable: (GSCSVariable *)lhs
equalsConstant: (CGFloat)rhs
{
GSCSLinearExpression *expression =
[[GSCSLinearExpression alloc] initWithVariable: lhs
coefficient: 1
constant: -rhs];
GSCSConstraint *constraint = [self initLinearConstraintWithExpression: expression];
RELEASE(expression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs
{
if (operator == GSCSConstraintOperatorEqual)
{
return AUTORELEASE([[GSCSConstraint alloc]
initWithLhsVariable: lhs equalsRhsVariable: rhs]);
}
else
{
GSCSLinearExpression *rhsExpression =
[[GSCSLinearExpression alloc] initWithVariable: rhs];
if (operator == GSCSConstraintOperationGreaterThanOrEqual)
{
[rhsExpression multiplyConstantAndTermsBy: -1];
[rhsExpression addVariable: lhs];
}
else if (operator == GSCSConstraintOperatorLessThanOrEqual)
{
[rhsExpression addVariable: lhs coefficient: -1];
}
RELEASE(rhsExpression);
return AUTORELEASE([[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: rhsExpression]);
}
}
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightConstant: (CGFloat)rhs
{
GSCSLinearExpression *expression;
GSCSConstraint *constraint;
if (operator == GSCSConstraintOperatorEqual)
{
expression = [[GSCSLinearExpression alloc] init];
[expression addVariable: lhs coefficient: 1];
[expression setConstant: -rhs];
constraint = [[GSCSConstraint alloc]
initLinearConstraintWithExpression: expression
strength: [GSCSStrength strengthRequired]
variable: nil];
}
else
{
expression =
[[GSCSLinearExpression alloc] initWithConstant: rhs];
if (operator == GSCSConstraintOperationGreaterThanOrEqual)
{
[expression multiplyConstantAndTermsBy: -1];
[expression addVariable: lhs coefficient: 1.0];
}
else if (operator == GSCSConstraintOperatorLessThanOrEqual)
{
[expression addVariable: lhs coefficient: -1.0];
}
constraint = [[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: expression];
}
RELEASE(expression);
return AUTORELEASE(constraint);
}
+ (GSCSConstraint *) constraintWithLeftVariable: (GSCSVariable *)lhs
operator: (GSCSConstraintOperator) operator
rightExpression: (GSCSLinearExpression *)rhs
{
GSCSLinearExpression *lhsExpression =
[[GSCSLinearExpression alloc] initWithVariable: lhs];
GSCSConstraint *constraint = [self constraintWithLeftExpression: lhsExpression operator: operator rightExpression: rhs];
RELEASE(lhsExpression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftConstant: (CGFloat)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs
{
GSCSLinearExpression *valueExpression =
[[GSCSLinearExpression alloc] initWithConstant: lhs];
GSCSConstraint *constraint = nil;
if (operator == GSCSConstraintOperatorEqual)
{
[valueExpression addVariable: rhs coefficient: -1.0];
constraint = [[GSCSConstraint alloc]
initLinearConstraintWithExpression: valueExpression];
}
else
{
if (operator == GSCSConstraintOperationGreaterThanOrEqual)
{
[valueExpression addVariable: rhs coefficient: -1.0];
}
else if (operator == GSCSConstraintOperatorLessThanOrEqual)
{
[valueExpression multiplyConstantAndTermsBy: -1];
[valueExpression addVariable: rhs coefficient: 1.0];
}
constraint = [[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: valueExpression];
}
RELEASE(valueExpression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightVariable: (GSCSVariable *)rhs
{
GSCSLinearExpression *rhsExpression =
[[GSCSLinearExpression alloc] initWithVariable: rhs];
GSCSConstraint *constraint = [self constraintWithLeftExpression: lhs operator: operator rightExpression: rhsExpression];
RELEASE(rhsExpression);
return constraint;
}
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightExpression: (GSCSLinearExpression *)rhs
{
GSCSLinearExpression *expression = [rhs copy];
GSCSConstraint *constraint;
if (operator == GSCSConstraintOperatorEqual)
{
[expression addExpression: lhs multiplier: -1];
constraint = [[GSCSConstraint alloc]
initLinearConstraintWithExpression: expression];
}
else
{
if (operator == GSCSConstraintOperationGreaterThanOrEqual)
{
[expression multiplyConstantAndTermsBy: -1];
[expression addExpression: lhs];
}
else if (operator == GSCSConstraintOperatorLessThanOrEqual)
{
[expression addExpression: lhs multiplier: -1];
}
constraint = [[GSCSConstraint alloc]
initLinearInequityConstraintWithExpression: expression];
}
RELEASE(expression);
return AUTORELEASE(constraint);
}
+ (GSCSConstraint *) constraintWithLeftExpression: (GSCSLinearExpression *)lhs
operator: (GSCSConstraintOperator) operator
rightConstant: (CGFloat)rhs
{
GSCSLinearExpression *rhsExpression =
[[GSCSLinearExpression alloc] initWithConstant: rhs];
GSCSConstraint *constraint = [self constraintWithLeftExpression: lhs operator: operator rightExpression: rhsExpression];
RELEASE(rhsExpression);
return constraint;
}
+ (instancetype) editConstraintWithVariable: (GSCSVariable *)variable
{
return AUTORELEASE([[self alloc]
initEditConstraintWithVariable: variable
strength: [GSCSStrength strengthStrong]]);
}
- (void) setStrength: (GSCSStrength *)strength
{
ASSIGN(_strength, strength);
}
- (BOOL) isRequired
{
return [_strength isRequired];
}
- (BOOL) isEditConstraint
{
return _type == GSCSConstraintTypeEdit;
}
- (BOOL) isStayConstraint
{
return _type == GSCSConstraintTypeStay;
}
- (BOOL) isInequality
{
return _type == GSCSConstraintTypeLinearInequity;
}
- (GSCSLinearExpression *) expression
{
return _expression;
}
- (GSCSVariable *) variable
{
return _variable;
}
- (GSCSStrength *) strength
{
return _strength;
}
- (GSCSConstraintType) type
{
return _type;
}
- (void) dealloc
{
RELEASE(_strength);
RELEASE(_expression);
RELEASE(_variable);
[super dealloc];
}
@end