void
WindowArea::DoGroupLayout()
{
	SATWindow* parentWindow = fWindowLayerOrder.ItemAt(0);
	if (parentWindow == NULL)
		return;

	BRect frame = parentWindow->CompleteWindowFrame();
	// Make it also work for solver which don't support negative variables
	frame.OffsetBy(kMakePositiveOffset, kMakePositiveOffset);

	// adjust window size soft constraints
	fWidthConstraint->SetRightSide(frame.Width());
	fHeightConstraint->SetRightSide(frame.Height());

	LinearSpec* linearSpec = fGroup->GetLinearSpec();
	Constraint* leftConstraint = linearSpec->AddConstraint(1.0, LeftVar(),
		kEQ, frame.left);
	Constraint* topConstraint = linearSpec->AddConstraint(1.0, TopVar(), kEQ,
		frame.top);

	// give soft constraints a high penalty
	fWidthConstraint->SetPenaltyNeg(kHighPenalty);
	fWidthConstraint->SetPenaltyPos(kHighPenalty);
	fHeightConstraint->SetPenaltyNeg(kHighPenalty);
	fHeightConstraint->SetPenaltyPos(kHighPenalty);

	// After we set the new parameter solve and apply the new layout.
	ResultType result;
	for (int32 tries = 0; tries < 15; tries++) {
		result = fGroup->GetLinearSpec()->Solve();
		if (result == kInfeasible) {
			debug_printf("can't solve constraints!\n");
			break;
		}
		if (result == kOptimal) {
			const WindowAreaList& areas = fGroup->GetAreaList();
			for (int32 i = 0; i < areas.CountItems(); i++) {
				WindowArea* area = areas.ItemAt(i);
				area->_MoveToSAT(parentWindow);
			}
			break;
		}
	}

	// set penalties back to normal
	fWidthConstraint->SetPenaltyNeg(kExtentPenalty);
	fWidthConstraint->SetPenaltyPos(kExtentPenalty);
	fHeightConstraint->SetPenaltyNeg(kExtentPenalty);
	fHeightConstraint->SetPenaltyPos(kExtentPenalty);

	linearSpec->RemoveConstraint(leftConstraint);
	linearSpec->RemoveConstraint(topConstraint);
}
Esempio n. 2
0
void
GroupCookie::DoGroupLayout(SATWindow* triggerWindow)
{
	if (!fSATGroup.Get())
		return;

	BRect frame = triggerWindow->CompleteWindowFrame();
	// Make it also work for solver which don't support negative variables
	frame.OffsetBy(kMakePositiveOffset, kMakePositiveOffset);

	// adjust window size soft constraints
	fWidthConstraint->SetRightSide(frame.Width());
	fHeightConstraint->SetRightSide(frame.Height());

	LinearSpec* linearSpec = fSATGroup->GetLinearSpec();
	fLeftConstraint = linearSpec->AddConstraint(1.0, fLeftBorder, kEQ,
		frame.left);
	fTopConstraint  = linearSpec->AddConstraint(1.0, fTopBorder, kEQ,
		frame.top);

	// adjust window position soft constraints
	// (a bit more penalty for them so they take precedence)
	fWidthConstraint->SetPenaltyNeg(-1);
	fWidthConstraint->SetPenaltyPos(-1);
	fHeightConstraint->SetPenaltyNeg(-1);
	fHeightConstraint->SetPenaltyPos(-1);

	// After we set the new parameter solve and apply the new layout.
	ResultType result;
	for (int32 tries = 0; tries < 15; tries++) {
		result = fSATGroup->GetLinearSpec()->Solve();
		if (result == kInfeasible) {
			debug_printf("can't solve constraints!\n");
			break;
		}
		if (result == kOptimal) {
			fSATGroup->AdjustWindows(triggerWindow);
			_UpdateWindowSize(frame);
			break;
		}
	}

	// set penalties back to normal
	fWidthConstraint->SetPenaltyNeg(kExtentPenalty);
	fWidthConstraint->SetPenaltyPos(kExtentPenalty);
	fHeightConstraint->SetPenaltyNeg(kExtentPenalty);
	fHeightConstraint->SetPenaltyPos(kExtentPenalty);

	linearSpec->RemoveConstraint(fLeftConstraint);
	fLeftConstraint = NULL;
	linearSpec->RemoveConstraint(fTopConstraint);
	fTopConstraint = NULL;
}
void
WindowArea::_UninitConstraints()
{
	LinearSpec* linearSpec = fGroup->GetLinearSpec();

	linearSpec->RemoveConstraint(fMinWidthConstraint, true);
	linearSpec->RemoveConstraint(fMinHeightConstraint, true);
	linearSpec->RemoveConstraint(fMaxWidthConstraint, true);
	linearSpec->RemoveConstraint(fMaxHeightConstraint, true);
	linearSpec->RemoveConstraint(fWidthConstraint, true);
	linearSpec->RemoveConstraint(fHeightConstraint, true);

	fMinWidthConstraint = NULL;
	fMinHeightConstraint = NULL;
	fMaxWidthConstraint = NULL;
	fMaxHeightConstraint = NULL;
	fWidthConstraint = NULL;
	fHeightConstraint = NULL;
}
bool
WindowArea::Init(SATGroup* group)
{
	_UninitConstraints();

	if (group != NULL && group->fWindowAreaList.AddItem(this) == false)
		return false;

	fGroup = group;

	LinearSpec* linearSpec = fGroup->GetLinearSpec();

	fMinWidthConstraint = linearSpec->AddConstraint(1.0, RightVar(), -1.0,
		LeftVar(), kGE, 0);
	fMinHeightConstraint = linearSpec->AddConstraint(1.0, BottomVar(), -1.0,
		TopVar(), kGE, 0);

	fMaxWidthConstraint = linearSpec->AddConstraint(1.0, RightVar(), -1.0,
		LeftVar(), kLE, 0, kInequalityPenalty, kInequalityPenalty);
	fMaxHeightConstraint = linearSpec->AddConstraint(1.0, BottomVar(), -1.0,
		TopVar(), kLE, 0, kInequalityPenalty, kInequalityPenalty);

	// Width and height have soft constraints
	fWidthConstraint = linearSpec->AddConstraint(1.0, RightVar(), -1.0,
		LeftVar(), kEQ, 0, kExtentPenalty,
		kExtentPenalty);
	fHeightConstraint = linearSpec->AddConstraint(-1.0, TopVar(), 1.0,
		BottomVar(), kEQ, 0, kExtentPenalty,
		kExtentPenalty);

	if (!fMinWidthConstraint || !fMinHeightConstraint || !fWidthConstraint
		|| !fHeightConstraint || !fMaxWidthConstraint
		|| !fMaxHeightConstraint)
		return false;

	return true;
}
Esempio n. 5
0
bool
GroupCookie::Init(SATGroup* group, WindowArea* area)
{
	ASSERT(fSATGroup.Get() == NULL);

	fSATGroup.SetTo(group);
	fWindowArea = area;

	LinearSpec* linearSpec = group->GetLinearSpec();
	// create variables
	fLeftBorder = linearSpec->AddVariable();
	fTopBorder = linearSpec->AddVariable();
	fRightBorder = linearSpec->AddVariable();
	fBottomBorder = linearSpec->AddVariable();

	if (!fLeftBorder || !fTopBorder || !fRightBorder || !fBottomBorder) {
		// clean up
		Uninit();
		return false;
	}

	// create constraints
	BRect frame = fSATWindow->CompleteWindowFrame();

	int32 minWidth, maxWidth, minHeight, maxHeight;
	fSATWindow->GetSizeLimits(&minWidth, &maxWidth, &minHeight,
		&maxHeight);
	fMinWidthConstraint = linearSpec->AddConstraint(1.0, fRightBorder, -1.0,
		fLeftBorder, kGE, minWidth);
	fMinHeightConstraint = linearSpec->AddConstraint(1.0, fBottomBorder, -1.0,
		fTopBorder, kGE, minHeight);

	// The width and height constraints have higher penalties than the
	// position constraints (left, top), so a window will keep its size
	// unless explicitly resized.
	fWidthConstraint = linearSpec->AddConstraint(-1.0, fLeftBorder, 1.0,
		fRightBorder, kEQ, frame.Width(), kExtentPenalty,
		kExtentPenalty);
	fHeightConstraint = linearSpec->AddConstraint(-1.0, fTopBorder, 1.0,
		fBottomBorder, kEQ, frame.Height(), kExtentPenalty,
		kExtentPenalty);

	if (!fMinWidthConstraint
		|| !fMinHeightConstraint || !fWidthConstraint || !fHeightConstraint) {
		// clean up
		Uninit();
		return false;
	}

	fLeftBorderConstraint = area->LeftTab()->Connect(fLeftBorder);
	fTopBorderConstraint = area->TopTab()->Connect(fTopBorder);
	fRightBorderConstraint = area->RightTab()->Connect(fRightBorder);
	fBottomBorderConstraint = area->BottomTab()->Connect(fBottomBorder);

	if (!fLeftBorderConstraint || !fTopBorderConstraint
		|| !fRightBorderConstraint || !fBottomBorderConstraint) {
		Uninit();
		return false;
	}

	return true;
}