Browse Source

Designed buttons for scrollbars.

David Piuva 5 years ago
parent
commit
fff2001a15

+ 39 - 1
Source/DFPSR/gui/VisualTheme.cpp

@@ -28,7 +28,6 @@
 
 
 namespace dsr {
 namespace dsr {
 
 
-// TODO: A sub-routine call drawing a rounded rectangle with a solid background
 // The default theme
 // The default theme
 //   Copy and modify and compile with theme_create to get a custom theme
 //   Copy and modify and compile with theme_create to get a custom theme
 static const ReadableString defaultThemeCode =
 static const ReadableString defaultThemeCode =
@@ -100,6 +99,32 @@ BEGIN: Button
 	PACK_RGBA: colorImage, redImage, greenImage, blueImage, visImage
 	PACK_RGBA: colorImage, redImage, greenImage, blueImage, visImage
 	END:
 	END:
 
 
+BEGIN: ScrollButton
+	INPUT: FixedPoint, width
+	INPUT: FixedPoint, height
+	INPUT: FixedPoint, pressed
+	INPUT: FixedPoint, red
+	INPUT: FixedPoint, green
+	INPUT: FixedPoint, blue
+	OUTPUT: ImageRgbaU8, colorImage
+	# Scale by 2 / 255 so that 127.5 represents full intensity in patternImage
+	MUL: normRed<FixedPoint>, red, 0.007843138
+	MUL: normGreen<FixedPoint>, green, 0.007843138
+	MUL: normBlue<FixedPoint>, blue, 0.007843138
+	CREATE: patternImage<ImageU8>, width, height
+	MUL: pressDarknessHigh<FixedPoint>, pressed, 80
+	MUL: pressDarknessLow<FixedPoint>, pressed, 10
+	SUB: highLuma<FixedPoint>, 150, pressDarknessHigh
+	SUB: lowLuma<FixedPoint>, 100, pressDarknessLow
+	FADE_LINEAR: patternImage,  0, 0, highLuma,  0, height, lowLuma
+	CALL: generate_rounded_rectangle, lumaImage<ImageU8>, width, height, 3, 1
+	MUL: lumaImage, lumaImage, patternImage, 0.003921569
+	MUL: redImage<ImageU8>, lumaImage, normRed
+	MUL: greenImage<ImageU8>, lumaImage, normGreen
+	MUL: blueImage<ImageU8>, lumaImage, normBlue
+	PACK_RGBA: colorImage, redImage, greenImage, blueImage, 255
+	END:
+
 BEGIN: Panel
 BEGIN: Panel
 	INPUT: FixedPoint, width
 	INPUT: FixedPoint, width
 	INPUT: FixedPoint, height
 	INPUT: FixedPoint, height
@@ -112,6 +137,19 @@ BEGIN: Panel
 	SUB: h2<FixedPoint>, height, 2
 	SUB: h2<FixedPoint>, height, 2
 	RECTANGLE: colorImage, 1, 1, w2, h2, red, green, blue, 255
 	RECTANGLE: colorImage, 1, 1, w2, h2, red, green, blue, 255
 	END:
 	END:
+
+BEGIN: ListBox
+	INPUT: FixedPoint, width
+	INPUT: FixedPoint, height
+	INPUT: FixedPoint, red
+	INPUT: FixedPoint, green
+	INPUT: FixedPoint, blue
+	OUTPUT: ImageRgbaU8, colorImage
+	CREATE: colorImage, width, height
+	SUB: w2<FixedPoint>, width, 2
+	SUB: h2<FixedPoint>, height, 2
+	RECTANGLE: colorImage, 1, 1, w2, h2, red, green, blue, 255
+	END:
 )QUOTE";
 )QUOTE";
 
 
 class VisualThemeImpl {
 class VisualThemeImpl {

+ 28 - 7
Source/DFPSR/gui/components/ListBox.cpp

@@ -67,7 +67,7 @@ void ListBox::generateGraphics() {
 	if (height < 1) { height = 1; }
 	if (height < 1) { height = 1; }
 	if (!this->hasImages) {
 	if (!this->hasImages) {
 		completeAssets();
 		completeAssets();
-	 	this->listBox(width, height, this->color.value.red, this->color.value.green, this->color.value.blue)(this->image);
+	 	this->scalableImage_listBox(width, height, this->color.value.red, this->color.value.green, this->color.value.blue)(this->image);
 		int verticalStep = this->font->size;
 		int verticalStep = this->font->size;
 		int left = textBorderLeft;
 		int left = textBorderLeft;
 		int top = textBorderTop;
 		int top = textBorderTop;
@@ -91,9 +91,9 @@ void ListBox::generateGraphics() {
 			ColorRgbaI32 barColor = ColorRgbaI32(this->color.value.red / 2, this->color.value.green / 2, this->color.value.blue / 2, 255);
 			ColorRgbaI32 barColor = ColorRgbaI32(this->color.value.red / 2, this->color.value.green / 2, this->color.value.blue / 2, 255);
 			ColorRgbaI32 borderColor = ColorRgbaI32(0, 0, 0, 255);
 			ColorRgbaI32 borderColor = ColorRgbaI32(0, 0, 0, 255);
 			IRect whole = IRect(this->location.width() - scrollWidth, 0, scrollWidth, this->location.height());
 			IRect whole = IRect(this->location.width() - scrollWidth, 0, scrollWidth, this->location.height());
-			IRect upper = IRect(whole.left() + border, whole.top() + border, whole.width() - border * 2, scrollEndHeight - border * 2);
+			IRect upper = IRect(whole.left(), whole.top(), whole.width(), scrollEndHeight);
 			IRect middle = IRect(whole.left() + border, whole.top() + scrollEndHeight + border, whole.width() - border * 2, whole.height() - (border + scrollEndHeight) * 2);
 			IRect middle = IRect(whole.left() + border, whole.top() + scrollEndHeight + border, whole.width() - border * 2, whole.height() - (border + scrollEndHeight) * 2);
-			IRect lower = IRect(whole.left() + border, whole.bottom() - scrollEndHeight + border, whole.width() - border * 2, scrollEndHeight - border * 2);
+			IRect lower = IRect(whole.left(), whole.bottom() - scrollEndHeight, whole.width(), scrollEndHeight);
 			IRect knob = this->getKnobLocation();
 			IRect knob = this->getKnobLocation();
 			// Scroll-bar
 			// Scroll-bar
 			draw_rectangle(this->image, whole, borderColor);
 			draw_rectangle(this->image, whole, borderColor);
@@ -101,6 +101,8 @@ void ListBox::generateGraphics() {
 			draw_rectangle(this->image, middle, barColor);
 			draw_rectangle(this->image, middle, barColor);
 			draw_rectangle(this->image, lower, buttonColor);
 			draw_rectangle(this->image, lower, buttonColor);
 			draw_rectangle(this->image, knob, buttonColor);
 			draw_rectangle(this->image, knob, buttonColor);
+			draw_copy(this->image, (this->pressScrollUp) ? this->scrollButtonTop_pressed : this->scrollButtonTop_normal, upper.left(), upper.top());
+			draw_copy(this->image, (this->pressScrollDown && this->inside) ? this->scrollButtonBottom_pressed : this->scrollButtonBottom_normal, lower.left(), lower.top());
 		}
 		}
 		this->hasImages = true;
 		this->hasImages = true;
 	}
 	}
@@ -112,13 +114,17 @@ void ListBox::drawSelf(ImageRgbaU8& targetImage, const IRect &relativeLocation)
 }
 }
 
 
 void ListBox::pressScrollBar(int64_t localY) {
 void ListBox::pressScrollBar(int64_t localY) {
+	int64_t oldIndex = this->firstVisible;
 	int64_t maxScroll = this->list.value.length() - this->getVisibleScrollRange();
 	int64_t maxScroll = this->list.value.length() - this->getVisibleScrollRange();
 	int64_t knobHeight = this->getKnobLocation().height();
 	int64_t knobHeight = this->getKnobLocation().height();
 	int64_t endDistance = scrollEndHeight + knobHeight / 2;
 	int64_t endDistance = scrollEndHeight + knobHeight / 2;
 	int64_t barHeight = this->location.height() - (endDistance * 2);
 	int64_t barHeight = this->location.height() - (endDistance * 2);
 	this->firstVisible = ((localY - endDistance) * maxScroll) / barHeight;
 	this->firstVisible = ((localY - endDistance) * maxScroll) / barHeight;
 	this->limitScrolling();
 	this->limitScrolling();
-	this->hasImages = false; // Force redraw
+	// Avoid expensive redrawing if the index did not change
+	if (this->firstVisible != oldIndex) {
+		this->hasImages = false; // Force redraw
+	}
 }
 }
 
 
 void ListBox::receiveMouseEvent(const MouseEvent& event) {
 void ListBox::receiveMouseEvent(const MouseEvent& event) {
@@ -135,9 +141,11 @@ void ListBox::receiveMouseEvent(const MouseEvent& event) {
 			this->pressedIndex = -1;
 			this->pressedIndex = -1;
 			if (event.position.y < scrollEndHeight) {
 			if (event.position.y < scrollEndHeight) {
 				// Upper scroll button
 				// Upper scroll button
+				this->pressScrollUp = true;
 				this->firstVisible--;
 				this->firstVisible--;
 			} else if (event.position.y > this->location.height() - scrollEndHeight) {
 			} else if (event.position.y > this->location.height() - scrollEndHeight) {
 				// Lower scroll button
 				// Lower scroll button
+				this->pressScrollDown = true;
 				this->firstVisible++;
 				this->firstVisible++;
 			} else {
 			} else {
 				// Start scrolling with the mouse using the relative height on the scroll bar.
 				// Start scrolling with the mouse using the relative height on the scroll bar.
@@ -162,6 +170,8 @@ void ListBox::receiveMouseEvent(const MouseEvent& event) {
 			this->limitScrolling(true);
 			this->limitScrolling(true);
 			this->callback_pressedEvent();
 			this->callback_pressedEvent();
 		}
 		}
+		this->pressScrollUp = false;
+		this->pressScrollDown = false;
 		this->pressedIndex = -1;
 		this->pressedIndex = -1;
 		this->holdingScrollBar = false;
 		this->holdingScrollBar = false;
 		this->hasImages = false; // Force redraw
 		this->hasImages = false; // Force redraw
@@ -185,14 +195,25 @@ void ListBox::receiveMouseEvent(const MouseEvent& event) {
 	}
 	}
 }
 }
 
 
+void ListBox::loadTheme(VisualTheme theme) {
+	this->scalableImage_listBox = theme_getScalableImage(theme, U"ListBox");
+	this->scalableImage_scrollButton = theme_getScalableImage(theme, U"ScrollButton");
+	// Generate fixed size buttons for the scroll buttons (because their size is currently given by constants)
+	ColorRgbI32 color = this->color.value;
+	this->scalableImage_scrollButton(scrollWidth, scrollEndHeight, false, color.red, color.green, color.blue)(this->scrollButtonTop_normal);
+	this->scalableImage_scrollButton(scrollWidth, scrollEndHeight, true, color.red, color.green, color.blue)(this->scrollButtonTop_pressed);
+	this->scalableImage_scrollButton(scrollWidth, scrollEndHeight, false, color.red, color.green, color.blue)(this->scrollButtonBottom_normal);
+	this->scalableImage_scrollButton(scrollWidth, scrollEndHeight, true, color.red, color.green, color.blue)(this->scrollButtonBottom_pressed);
+}
+
 void ListBox::changedTheme(VisualTheme newTheme) {
 void ListBox::changedTheme(VisualTheme newTheme) {
-	this->listBox = theme_getScalableImage(newTheme, U"Panel");
+	this->loadTheme(newTheme);
 	this->hasImages = false; // Force redraw
 	this->hasImages = false; // Force redraw
 }
 }
 
 
 void ListBox::completeAssets() {
 void ListBox::completeAssets() {
-	if (this->listBox.methodIndex == -1) {
-		this->listBox = theme_getScalableImage(theme_getDefault(), U"Panel");
+	if (this->scalableImage_listBox.methodIndex == -1) {
+		this->loadTheme(theme_getDefault());
 	}
 	}
 	if (this->font.get() == nullptr) {
 	if (this->font.get() == nullptr) {
 		this->font = font_getDefault();
 		this->font = font_getDefault();

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

@@ -40,6 +40,8 @@ public:
 	Persistent* findAttribute(const ReadableString &name) override;
 	Persistent* findAttribute(const ReadableString &name) override;
 private:
 private:
 	// Temporary
 	// Temporary
+	bool pressScrollUp = false;
+	bool pressScrollDown = false;
 	bool holdingScrollBar = false;
 	bool holdingScrollBar = false;
 	int64_t knobHoldOffset = 0; // The number of pixels down from the center that the knob grabbed last time.
 	int64_t knobHoldOffset = 0; // The number of pixels down from the center that the knob grabbed last time.
 	bool inside = false;
 	bool inside = false;
@@ -47,12 +49,14 @@ private:
 	int64_t pressedIndex = -1; // Index of pressed item or -1 for none.
 	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.
 	int64_t firstVisible = 0; // Index of first visible element for scrolling. May never go below zero.
 	// Given from the style
 	// Given from the style
-	MediaMethod listBox;
+	MediaMethod scalableImage_listBox;
+	MediaMethod scalableImage_scrollButton;
 	std::shared_ptr<RasterFont> font;
 	std::shared_ptr<RasterFont> font;
 	void completeAssets();
 	void completeAssets();
 	void generateGraphics();
 	void generateGraphics();
 	// Generated
 	// Generated
 	bool hasImages = false;
 	bool hasImages = false;
+	OrderedImageRgbaU8 scrollButtonTop_normal, scrollButtonTop_pressed, scrollButtonBottom_normal, scrollButtonBottom_pressed;
 	OrderedImageRgbaU8 image;
 	OrderedImageRgbaU8 image;
 	// Helper methods
 	// Helper methods
 	// Returns the selected index referring to an existing element or -1 if none is selected
 	// Returns the selected index referring to an existing element or -1 if none is selected
@@ -64,6 +68,7 @@ private:
 	IRect getScrollBarLocation_excludingButtons(); // Return the location of the scroll-bar without buttons
 	IRect getScrollBarLocation_excludingButtons(); // Return the location of the scroll-bar without buttons
 	IRect getKnobLocation(); // Return the location of the scroll-bar's knob
 	IRect getKnobLocation(); // Return the location of the scroll-bar's knob
 	void pressScrollBar(int64_t localY); // Press the scroll-bar at localY in pixels
 	void pressScrollBar(int64_t localY); // Press the scroll-bar at localY in pixels
+	void loadTheme(VisualTheme theme);
 public:
 public:
 	ListBox();
 	ListBox();
 public:
 public: