Browse Source

Automatically locking ListBox scrolling when all can be displayed at once.

David Piuva 5 years ago
parent
commit
0ba6760622
2 changed files with 23 additions and 9 deletions
  1. 21 8
      Source/DFPSR/gui/components/ListBox.cpp
  2. 2 1
      Source/DFPSR/gui/components/ListBox.h

+ 21 - 8
Source/DFPSR/gui/components/ListBox.cpp

@@ -107,6 +107,7 @@ void ListBox::receiveMouseEvent(const MouseEvent& event) {
 	} else if (this->pressedIndex > -1 && event.mouseEventType == MouseEventType::MouseUp) {
 		if (this->inside && hoverIndex == this->pressedIndex) {
 			this->selectedIndex.value = hoverIndex;
+			this->limitScrolling(true);
 			this->callback_pressedEvent();
 		}
 		this->pressedIndex = -1;
@@ -178,22 +179,34 @@ void ListBox::limitSelection() {
 
 // Optional limit of scrolling, to be applied when the user don't explicitly scroll away from the selection
 // limitSelection should be called before limitScrolling, because scrolling limits depend on selection
-void ListBox::limitScrolling() {
+void ListBox::limitScrolling(bool keepSelectedVisible) {
 	if (this->lockScrolling.value) {
 		this->firstVisible = 0;
+		this->hasVerticalScroll = false;
 	} else {
 		// Try to load the font before estimating how big the view is
 		this->completeAssets();
 		if (this->font.get() == nullptr) {
 			throwError("Cannot get the font size because ListBox failed to get a font!\n");
 		}
-		int visibleRange = this->location.height() / (this->font->size);
-		int maxScroll = this->selectedIndex.value;
-		int minScroll = maxScroll + 1 - visibleRange;
+		int itemCount = this->list.value.length();
+		int verticalStep = this->font->size;
+		int visibleRange = (this->location.height() - textBorderTop * 2) / verticalStep;
+		int maxScroll;
+		int minScroll;
+		this->hasVerticalScroll = itemCount > visibleRange;
+		if (keepSelectedVisible) {
+			maxScroll = this->selectedIndex.value;
+			minScroll = maxScroll + 1 - visibleRange;
+		} else {
+			maxScroll = itemCount - visibleRange;
+			minScroll = 0;
+		}
+		if (this->firstVisible > maxScroll) {
+			this->firstVisible = maxScroll;
+		}
 		if (this->firstVisible < minScroll) {
 			this->firstVisible = minScroll;
-		} else if (this->firstVisible > maxScroll) {
-			this->firstVisible = maxScroll;
 		}
 	}
 }
@@ -211,7 +224,7 @@ String ListBox::call(const ReadableString &methodName, const ReadableString &arg
 		// No quote mangling needed for this single argument.
 		this->list.value.push(arguments);
 		this->selectedIndex.value = this->list.value.length() - 1;
-		this->limitScrolling();
+		this->limitScrolling(true);
 		this->hasImages = false;
 		return U"";
 	} else if (string_caseInsensitiveMatch(methodName, U"RemoveElement")) {
@@ -222,7 +235,7 @@ String ListBox::call(const ReadableString &methodName, const ReadableString &arg
 		}
 		this->list.value.remove(index);
 		this->limitSelection();
-		this->limitScrolling();
+		this->limitScrolling(true);
 		this->hasImages = false;
 		return U"";
 	} else if (string_caseInsensitiveMatch(methodName, U"GetLength")) {

+ 2 - 1
Source/DFPSR/gui/components/ListBox.h

@@ -43,6 +43,7 @@ private:
 	// Temporary
 	bool pressed = false;
 	bool inside = false;
+	bool hasVerticalScroll = false;
 	int64_t pressedIndex = -1; // Index of pressed item or -1 for none.
 	int64_t firstVisible = 0; // Index of first visible element for scrolling. May never go below zero.
 	// Given from the style
@@ -57,7 +58,7 @@ private:
 	// Returns the selected index referring to an existing element or -1 if none is selected
 	int64_t getSelectedIndex();
 	void limitSelection();
-	void limitScrolling();
+	void limitScrolling(bool keepSelectedVisible = false);
 public:
 	ListBox();
 public: