bool SATGroup::_FindConnectedGroup(WindowAreaList& seedList, WindowArea* removedArea, WindowAreaList& newGroup) { if (seedList.CountItems() == 0) return false; WindowArea* area = seedList.RemoveItemAt(0); newGroup.AddItem(area); _FollowSeed(area, removedArea, seedList, newGroup); return true; }
void SATGroup::_SpawnNewGroup(const WindowAreaList& newGroup) { STRACE_SAT("SATGroup::_SpawnNewGroup\n"); SATGroup* group = new (std::nothrow)SATGroup; if (!group) return; BReference<SATGroup> groupRef; groupRef.SetTo(group, true); for (int i = 0; i < newGroup.CountItems(); i++) newGroup.ItemAt(i)->PropagateToGroup(group); _EnsureGroupIsOnScreen(group); }
void SATGroup::_BottomNeighbours(WindowAreaList& neighbourWindows, WindowArea* parent) { float startPos = parent->LeftBottomCrossing()->VerticalTab()->Position(); float endPos = parent->RightBottomCrossing()->VerticalTab()->Position(); Tab* tab = parent->LeftBottomCrossing()->HorizontalTab(); const CrossingList* crossingList = tab->GetCrossingList(); for (int i = 0; i < crossingList->CountItems(); i++) { Corner* corner = crossingList->ItemAt(i)->LeftBottomCorner(); if (corner->status != Corner::kUsed) continue; WindowArea* area = corner->windowArea; float pos1 = area->LeftBottomCrossing()->VerticalTab()->Position(); float pos2 = area->RightBottomCrossing()->VerticalTab()->Position(); if (pos1 < endPos && pos2 > startPos) neighbourWindows.AddItem(area); if (pos2 > endPos) break; } }
void SATGroup::_SplitGroupIfNecessary(WindowArea* removedArea) { // if there are windows stacked in the area we don't need to split if (!removedArea || removedArea->WindowList().CountItems() > 1) return; WindowAreaList neighbourWindows; _FillNeighbourList(neighbourWindows, removedArea); bool ownGroupProcessed = false; WindowAreaList newGroup; while (_FindConnectedGroup(neighbourWindows, removedArea, newGroup)) { STRACE_SAT("Connected group found; %i window(s)\n", (int)newGroup.CountItems()); if (newGroup.CountItems() == 1 && newGroup.ItemAt(0)->WindowList().CountItems() == 1) { SATWindow* window = newGroup.ItemAt(0)->WindowList().ItemAt(0); RemoveWindow(window); _EnsureGroupIsOnScreen(window->GetGroup()); } else if (ownGroupProcessed) _SpawnNewGroup(newGroup); else { _EnsureGroupIsOnScreen(this); ownGroupProcessed = true; } newGroup.MakeEmpty(); } }
void SATGroup::_FollowSeed(WindowArea* area, WindowArea* veto, WindowAreaList& seedList, WindowAreaList& newGroup) { WindowAreaList neighbours; _FillNeighbourList(neighbours, area); for (int i = 0; i < neighbours.CountItems(); i++) { WindowArea* currentArea = neighbours.ItemAt(i); if (currentArea != veto && !newGroup.HasItem(currentArea)) { newGroup.AddItem(currentArea); // if we get a area from the seed list it is not a seed any more seedList.RemoveItem(currentArea); } else { // don't _FollowSeed of invalid areas neighbours.RemoveItemAt(i); i--; } } for (int i = 0; i < neighbours.CountItems(); i++) _FollowSeed(neighbours.ItemAt(i), veto, seedList, newGroup); }