FileDialog - Optymalizacja rekurencyjnie wypisywanych lokacji plików

FileDialog - Optymalizacja rekurencyjnie wypisywanych lokacji plików
tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 582
0

Cześć. :-)
Napisałem sobie File Dialog. tj okienko do listowania plików w katalogu. Lista dla plików jest optymalizowana w ten sposób, że wyświetlanych jest elementów wysokość_panelu/wysokość_itemu + 1.
Dzięki temu wyświetlam stałą liczbę itemów dla plików i folderów. Chciałbym teraz optymalizować w podobny sposób lokacje po lewej stronie. Problematyczne jest to, że nie wiem jak to zrobić z rekurencyjnym przetwarzaniem katalogów (bo niektóre mogą być otwarte stąd ta rekurencja).

Ma ktoś pomysł jak to optymalizować? :-)

FileDialog.png

optymalizacja listowania plików i katalogów w prawym oknie (% basic_text_rect_height)

Kopiuj
for (int i = 0; i < _files.size(); i++) {
	std::filesystem::path path = _filesPaths[i + scrollbarValue/ basic_text_rect_height];
	_files[i]->setFile(path);
	sf::Vector2i pos;
	pos.x = _rightRect->position.x;
	pos.y = _rightRect->position.y + (i * basic_text_rect_height) - _rightScrollbar->getValue() % basic_text_rect_height;
	//std::wcout << rightScrollbar->getValue() << " : " << pos.y << L"\n";
	_files[i]->setPosition(pos);
}

rysowanie lewego panelu bez optymalizacji ale z przycinaniem obrazu do okienka

Kopiuj
float LocationRect::getTotalHeight() {
	float h = (float)_rect.size.y;

	if (_isOpen) {
		for (auto& child : _children) {
			h += child->getTotalHeight();
		}
	}
	return h;
}

void FileDialog::drawLeftPanel() {
	// ograniczenie widoku do rozmiaru recta
	sf::View view(sf::FloatRect(
		sf::Vector2f((float)_leftRect->position.x, (float)_leftRect->position.y),
		sf::Vector2f((float)_leftRect->size.x, (float)_leftRect->size.y)
	));

	sf::FloatRect vp(
		sf::Vector2f((float)_leftRect->position.x / mainView.getSize().x, (float)_leftRect->position.y / mainView.getSize().y),
		sf::Vector2f((float)_leftRect->size.x / mainView.getSize().x, (float)_leftRect->size.y / mainView.getSize().y)
	);

	// ustawienie widoku
	view.setViewport(vp);
	window->setView(view);

	/*
	sf::RectangleShape leftRect(sf::Vector2f(_leftRect.size));
	leftRect.setPosition(sf::Vector2f(_leftRect.position));
	leftRect.setFillColor(sf::Color(255, 47, 47, 127));
	window->draw(leftRect);
	*/

	// pozycjonowanie itemów folderów
	sf::Vector2i pos;
	pos.x = getContentPosition().x + dialog_padding;
	pos.y = getContentPosition().y - _leftScrollbar->getValue();
	for (int i = 0; i < _locations.size(); i++) {
		_locations[i]->setPosition(pos);
		pos.y += (int)_locations[i]->getTotalHeight();
	}

	// desktop/documents/pictures etc.
	for (auto& fav : _locations)
		fav->draw();

	
}
several
  • Rejestracja: dni
  • Ostatnio: dni
0

Na screenshocie wygląda względnie ok, nie do końca rozumiem co tam chcesz zrobić.

tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 582
0

No bo działa ale nie optymalnie :-) Chcę ograniczyć renderowanie elementów lewego panelu do tylko tych widocznych. Potrzebuje jakoś wyznaczyć index początkowy elementu i index końcowy i jakoś to optymalniej renderować.

tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 582
0

Można by sprawdzać dla wszystkich lokacji po kolei intersection z panelem, ale to nie wydaje się optymalnym rozwiązaniem, bo trzeba przejrzeć je wszystkie...

Potrzebowałbym index pierwszego widocznego katalogu, ostatniego widocznego katalogu i jakoś to renderować

tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 582
0

No mniej więcej tak to trzeba zrobić. :-) trzymaj, może kiedyś się to Tobie przyda :-)

Kopiuj
void FileDialog::buildVisibleLocations() {

	_visibleLocations.clear();

	for (auto& location : _locations) {
		addVisibleLocation(location);
	}

	updateLeftScrollbar();
}
Kopiuj
void FileDialog::addVisibleLocation(std::shared_ptr<LocationRect> location) {

	if (!location)
		return;

	_visibleLocations.push_back(location);

	if (location->_isOpen) {
		for (auto& child : location->_children) {
			addVisibleLocation(child);
		}
	}
}
Kopiuj

void FileDialog::createLeftPanel(int dictionariesCount) {

	sf::Vector2i rectSize = sf::Vector2i(100, dictionariesCount * basic_text_rect_height);
	_leftRect = std::make_shared<sf::IntRect>(sf::Vector2i(0,0), rectSize);

	const wchar_t* userProfile = _wgetenv(L"USERPROFILE");
	std::wstring up(userProfile);

	// dictionaries
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\AppData\\Roaming\\Microsoft\\Windows\\Recent"));
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\Documents"));
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\Music"));
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\Pictures"));
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\Downloads"));
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\Desktop"));
	_locations.push_back(std::make_shared<LocationRect>(up + L"\\Videos"));

	// load the harddrivers
	DWORD drives = GetLogicalDrives();
	for (int i = 0; i < 32; i++)
		if ((drives >> i) & 1) {
			//printf("%c:\\\n", 'A' + i);
			_locations.push_back(std::make_shared<LocationRect>(std::wstring(1, L'A' + i) + L":\\"));
		}

	for (int i = 0; i < _locations.size(); i++) {
		_locations[i]->setSize(sf::Vector2i(_leftRect->size.x, basic_text_rect_height));
		
		_locations[i]->_onTreeChanged = [this]() {
			buildVisibleLocations();
			setPosition(_position);
			};

		// KLIK W NAZWĘ -> otwórz po PRAWEJ
		_locations[i]->_onclick_location_func = [this, i]() {
			currentPath = _locations[i]->_path.wstring();
			loadDirectory();
			_rightScrollbar->setMax((int)(_filesPaths.size() - _files.size() + 1) * basic_text_rect_height);
			_rightScrollbar->setValue(0);
			setTheFiles();
			setPosition(_position);
			};

		// KLIK W STRZAŁKĘ -> tylko rozwiń/zwiń po LEWEJ
		_locations[i]->_onclick_arrow_func = [this, i]() {
			auto& node = _locations[i];
			if (!node->_hasChildren) return;

			if (node->_isOpen) {
				node->close();
			}
			else {
				// UWAGA: przekazujemy onPick, żeby POTOMKOWIE mieli poprawny "open po prawej"
				node->open([this](const std::wstring& newPath) {
					currentPath = newPath;
					loadDirectory();
					_rightScrollbar->setMax((int)(_filesPaths.size() - _files.size() + 1) * basic_text_rect_height);
					_rightScrollbar->setValue(0);
					setTheFiles();
					setPosition(_position);
					});
			}

			buildVisibleLocations();
			setPosition(_position);

			};
	}

	// scrollbar
	sf::Vector2i scrollbarPos;
	scrollbarPos.x = _leftRect->position.x + _leftRect->size.x + dialog_padding;
	scrollbarPos.y = getContentPosition().y;

	sf::Vector2i scrollbarSize = sf::Vector2i(16, _leftRect->size.y);

	int scrollbarMax = 0;
	int scrollbarSliderSize = (dictionariesCount - 1) * basic_text_rect_height;

	_leftScrollbar = std::make_shared<Scrollbar>(scrollbarPos.x, scrollbarPos.y, scrollbarSize.x, scrollbarSize.y, 0, scrollbarMax, scrollbarSliderSize, 0);
	_leftScrollbar->_func = [this]() { 
		setTheFiles();
		setPosition(_position);
		};
	_leftScrollbar->setScrollArea(_leftRect, basic_text_rect_height * 0.5f);

	buildVisibleLocations();
}
Kopiuj
void FileDialog::update() {
	Dialog::update();

	for (auto& file : _files)
		file->update();

	auto visibleLocations = _visibleLocations;

	for (auto& location : visibleLocations) {
		location->update();
	}
    // ...
    

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.