diff --git a/TODO.txt b/TODO.txt index e223b09..e71bc19 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,6 +1,4 @@ Desenvolver componentes: - Barra de rolagem; - Painel de rolagem? Área de texto. Separar o exemplos futuramente. \ No newline at end of file diff --git a/nbproject/project.properties b/nbproject/project.properties index 55981ef..403f0fd 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -88,7 +88,7 @@ jnlp.signed=false jnlp.signing= jnlp.signing.alias= jnlp.signing.keystore= -main.class=br.com.davidbuzatto.jsge.examples.JSGEShowcaseWindow +main.class=br.com.davidbuzatto.jsge.examples.basic.IMGUIExample # Optional override of default Application-Library-Allowable-Codebase attribute identifying the locations where your signed RIA is expected to be found. manifest.custom.application.library.allowable.codebase= # Optional override of default Caller-Allowable-Codebase attribute identifying the domains from which JavaScript code can make calls to your RIA without security prompts. diff --git a/src/br/com/davidbuzatto/jsge/Bundle.properties b/src/br/com/davidbuzatto/jsge/Bundle.properties index 9e9cb2c..4cd6c62 100644 --- a/src/br/com/davidbuzatto/jsge/Bundle.properties +++ b/src/br/com/davidbuzatto/jsge/Bundle.properties @@ -1 +1 @@ -JSGE.version=v1.5.1 \ No newline at end of file +JSGE.version=v1.5.2 \ No newline at end of file diff --git a/src/br/com/davidbuzatto/jsge/examples/basic/IMGUIExample.java b/src/br/com/davidbuzatto/jsge/examples/basic/IMGUIExample.java index a6baeb1..137e10c 100644 --- a/src/br/com/davidbuzatto/jsge/examples/basic/IMGUIExample.java +++ b/src/br/com/davidbuzatto/jsge/examples/basic/IMGUIExample.java @@ -102,11 +102,9 @@ public class IMGUIExample extends EngineFrame { private GuiInputDialog inputDialog; private GuiConfirmDialog confirmDialog; - private GuiWindow glueWindow; - private GuiLabel glueLabel; - private GuiButton glueButton; - private GuiDropdownList glueDropdownList; - private GuiColorPicker glueColorPicker; + private GuiWindow themeWindow; + private GuiButton themeButton; + private GuiColorPicker themeColorPicker; private GuiGlue glue; private GuiToolTip toolTipLabel1; @@ -133,6 +131,7 @@ public class IMGUIExample extends EngineFrame { private GuiTheme lightTheme; private GuiTheme darkTheme; private GuiTheme currentTheme; + private GuiTheme coloredTheme; private ChangeThemeButton changeThemeButton; private Image sunIcon; @@ -154,6 +153,7 @@ public void create() { lightTheme = GuiTheme.buildLightTheme(); darkTheme = GuiTheme.buildDarkTheme(); + coloredTheme = GuiTheme.buildColoredTheme( EngineFrame.BLUE ); currentTheme = lightTheme; int x = 20; @@ -280,21 +280,17 @@ public void create() { x = 820; y = 30; - glueWindow = new GuiWindow( x, y, 240, 160, "Glue Example (drag me!)" ); - glueLabel = new GuiLabel( 0, 0, 100, 30, "Glued Label" ); - glueButton = new GuiButton( 0, 0, 100, 30, "Glued Button" ); - glueDropdownList = new GuiDropdownList( 0, 0, 100, 30, List.of( "1", "2", "3", "4", "5", "6" ) ); - glueColorPicker = new GuiColorPicker( 0, 0, 85, 85, Color.RED ); - - glue = new GuiGlue( glueWindow ); - glue.addChild( glueLabel, 10, 40 ); - glue.addChild( glueButton, 10, 80 ); - glue.addChild( glueDropdownList, 10, 120 ); - glue.addChild( glueColorPicker, glueDropdownList.getX() - glueWindow.getX() + glueDropdownList.getWidth() + 10, 40 ); + themeWindow = new GuiWindow( x, y, 240, 160, "Theme Color (drag me!)" ); + themeButton = new GuiButton( 0, 0, 100, 85, "Apply Color" ); + themeColorPicker = new GuiColorPicker( 0, 0, 85, 85, EngineFrame.BLUE ); + + glue = new GuiGlue( themeWindow ); + glue.addChild( themeColorPicker, 10, 40 ); + glue.addChild( themeButton, 130, 40 ); components.add( glue ); vSpacing = 30; - y += glueWindow.getHeight() + 10; + y += themeWindow.getHeight() + 10; checkEnabled = new GuiCheckBox( x, y, 100, 20, "Enabled" ); checkEnabled.setSelected( true ); checkVisible = new GuiCheckBox( x, y += vSpacing, 100, 20, "Visible" ); @@ -382,11 +378,11 @@ public void update( double delta ) { draggedComponent = windowUntitled; } - if ( glueWindow.isCloseButtonPressed() ) { + if ( themeWindow.isCloseButtonPressed() ) { glue.setVisible( false ); } - if ( glueWindow.isTitleBarPressed() ) { + if ( themeWindow.isTitleBarPressed() ) { draggedComponent = glue; } @@ -470,6 +466,15 @@ public void update( double delta ) { draggedComponent = confirmDialog; } + if ( themeButton.isMousePressed() ) { + coloredTheme = GuiTheme.buildColoredTheme( themeColorPicker.getColor() ); + currentTheme = coloredTheme; + currentTheme.apply( components ); + currentTheme.apply( interactionComponents ); + currentTheme.install(); + changeThemeButton.activeTheme = ChangeThemeButton.COLORED_THEME; + } + checkEnabled.update( delta ); checkVisible.update( delta ); checkDrawBounds.update( delta ); @@ -501,11 +506,18 @@ public void update( double delta ) { } if ( changeThemeButton.isMousePressed() ) { - changeThemeButton.darkThemeActive = !changeThemeButton.darkThemeActive; - if ( changeThemeButton.darkThemeActive ) { - currentTheme = darkTheme; - } else { - currentTheme = lightTheme; + changeThemeButton.activeTheme = (changeThemeButton.activeTheme++) % 3 + 1; + switch ( changeThemeButton.activeTheme ) { + case ChangeThemeButton.LIGHT_THEME: + currentTheme = lightTheme; + break; + case ChangeThemeButton.DARK_THEME: + currentTheme = darkTheme; + break; + case ChangeThemeButton.COLORED_THEME: + currentTheme = coloredTheme; + break; + } currentTheme.apply( components ); currentTheme.apply( interactionComponents ); @@ -603,7 +615,7 @@ public void draw() { drawText( messageDialogStatus, 650, buttonShowMessageDialog.getBounds().y + buttonShowMessageDialog.getBounds().height / 2 - 3, 12, currentTheme.borderColor ); drawText( inputDialogStatus, 650, buttonShowInputDialog.getBounds().y + buttonShowInputDialog.getBounds().height / 2 - 3, 12, currentTheme.borderColor ); - drawText( confirmDialogStatus, 650, buttonShowConfirmDialog.getBounds().y + buttonShowConfirmDialog.getBounds().height / 2 - 3, 12, GRAY ); + drawText( confirmDialogStatus, 650, buttonShowConfirmDialog.getBounds().y + buttonShowConfirmDialog.getBounds().height / 2 - 3, 12, currentTheme.borderColor ); drawColoredRectangle( 675, colorPicker.getBounds().y + colorPicker.getBounds().height / 2 - 40, colorPicker.getColor() ); @@ -663,7 +675,11 @@ private void drawColoredRectangle( double x, double y, Color color ) { private class ChangeThemeButton extends GuiComponent { - private boolean darkThemeActive; + private static final int LIGHT_THEME = 1; + private static final int DARK_THEME = 2; + private static final int COLORED_THEME = 3; + + private int activeTheme; private Image sunIcon; private Image moonIcon; @@ -671,21 +687,29 @@ public ChangeThemeButton( double x, double y, double width, double height, Image super( x, y, width, height ); this.sunIcon = sunIcon; this.moonIcon = moonIcon; + this.activeTheme = LIGHT_THEME; } public ChangeThemeButton( double x, double y, double width, double height, Image sunIcon, Image moonIcon, EngineFrame engine ) { super( x, y, width, height, engine ); this.sunIcon = sunIcon; this.moonIcon = moonIcon; + this.activeTheme = LIGHT_THEME; } @Override public void draw() { fillRectangle( bounds, backgroundColor ); - if ( darkThemeActive ) { - drawImage( moonIcon, bounds.x, bounds.y ); - } else { - drawImage( sunIcon, bounds.x, bounds.y ); + switch ( activeTheme ) { + case LIGHT_THEME: + drawImage( sunIcon, bounds.x, bounds.y ); + break; + case DARK_THEME: + drawImage( moonIcon, bounds.x, bounds.y ); + break; + case COLORED_THEME: + drawText( "C", bounds.x + 10, bounds.y + 7, 50, textColor ); + break; } drawRectangle( bounds, borderColor ); } diff --git a/src/br/com/davidbuzatto/jsge/imgui/GuiComponent.java b/src/br/com/davidbuzatto/jsge/imgui/GuiComponent.java index 92c5bd8..831ba49 100644 --- a/src/br/com/davidbuzatto/jsge/imgui/GuiComponent.java +++ b/src/br/com/davidbuzatto/jsge/imgui/GuiComponent.java @@ -61,6 +61,9 @@ public abstract class GuiComponent { /** Raio do componente deslizante. */ public static final double SLIDER_RADIUS = 10; + /** Tamanho do botão da barra de rolagem. */ + public static final double SCROLL_BAR_BUTTON_SIZE = 20; + //************************************************************************** // Cores. // Os nomes são mantidos em maiúsculas para não misturar com os atributos. @@ -128,9 +131,9 @@ public abstract class GuiComponent { /** Cor de fundo para os contâineres de itens dos componentes de lista desabilitados. */ public static Color DISABLED_LIST_CONTAINER_BACKGROUND_COLOR; - /** Cor de fundo para a trila dos sliders usados como barras de rolagem. */ + /** Cor de fundo para a trila das barras de rolagem. */ public static Color SCROLL_BAR_TRACK_COLOR; - /** Cor de fundo para a trila dos sliders desabiltiados usados como barras de rolagem. */ + /** Cor de fundo para a trila das barras de rolagem desabiltiadas. */ public static Color DISABLED_SCROLL_BAR_TRACK_COLOR; /** Cor da sobreposição do seletor de cor quando está desabilitado. */ diff --git a/src/br/com/davidbuzatto/jsge/imgui/GuiDropdownList.java b/src/br/com/davidbuzatto/jsge/imgui/GuiDropdownList.java index 9bafbed..50688d0 100644 --- a/src/br/com/davidbuzatto/jsge/imgui/GuiDropdownList.java +++ b/src/br/com/davidbuzatto/jsge/imgui/GuiDropdownList.java @@ -236,24 +236,6 @@ public boolean isDropdownListVisible() { return itemsList.isVisible(); } - /** - * Obtém a cor do caminho da barra de rolagem. - * - * @return A cor do caminho da barra de rolagem. - */ - public Color getScrollBarTrackColor() { - return itemsList.scrollBarTrackColor; - } - - /** - * Configura a cor do caminho da barra de rolagem. - * - * @param scrollBarTrackColor A cor do caminho da barra de rolagem. - */ - public void setScrollBarTrackColor( Color scrollBarTrackColor ) { - this.itemsList.scrollBarTrackColor = scrollBarTrackColor; - } - /** * Obtém a cor do fundo da barra de rolagem. * @@ -307,24 +289,6 @@ public Color getScrollBarTextColor() { public void setScrollBarTextColor( Color textColor ) { itemsList.scrollBar.setTextColor( textColor ); } - - /** - * Obtém a cor do preenchimento da barra de rolagem. - * - * @return A cor do preenchimento. - */ - public Color getScrollBarTrackFillColor() { - return itemsList.scrollBar.getTrackFillColor(); - } - - /** - * Confira a cor do preenchimento da barra de rolagem. - * - * @param trackFillColor A cor do preenchimento. - */ - public void setScrollBarTrackFillColor( Color trackFillColor ) { - itemsList.scrollBar.setTrackFillColor( trackFillColor ); - } @Override public void setBackgroundColor( Color backgroundColor ) { diff --git a/src/br/com/davidbuzatto/jsge/imgui/GuiList.java b/src/br/com/davidbuzatto/jsge/imgui/GuiList.java index 9f10f06..7a39856 100644 --- a/src/br/com/davidbuzatto/jsge/imgui/GuiList.java +++ b/src/br/com/davidbuzatto/jsge/imgui/GuiList.java @@ -38,7 +38,7 @@ public class GuiList extends GuiComponent { private List items; private double itemTextHeight; - protected GuiSlider scrollBar; + protected GuiScrollBar scrollBar; private boolean useScrollBar; private double itemsHeight; private double heightDiff; @@ -46,8 +46,6 @@ public class GuiList extends GuiComponent { private double scrollOffset; private double prevScrollOffset; - protected Color scrollBarTrackColor; - /** * Cria o componente. * @@ -117,16 +115,15 @@ public GuiList( Rectangle bounds, List itemsText ) { private void initComponents( EngineFrame engine, List itemsText ) { if ( engine == null ) { - scrollBar = new GuiSlider( bounds.x + bounds.width, bounds.y, SLIDER_RADIUS * 2, bounds.height, itemsText.size(), 0, itemsText.size(), GuiSlider.VERTICAL ); + scrollBar = new GuiScrollBar( bounds.x + bounds.width, bounds.y, SLIDER_RADIUS * 2, bounds.height, itemsText.size(), 0, itemsText.size(), GuiSlider.VERTICAL ); } else { - scrollBar = new GuiSlider( bounds.x + bounds.width, bounds.y, SLIDER_RADIUS * 2, bounds.height, itemsText.size(), 0, itemsText.size(), GuiSlider.VERTICAL, engine ); + scrollBar = new GuiScrollBar( bounds.x + bounds.width, bounds.y, SLIDER_RADIUS * 2, bounds.height, itemsText.size(), 0, itemsText.size(), GuiSlider.VERTICAL, engine ); } this.itemsText = itemsText; this.items = new ArrayList<>(); this.useScrollBar = true; this.backgroundColor = LIST_CONTAINER_BACKGROUND_COLOR; - this.scrollBarTrackColor = SCROLL_BAR_TRACK_COLOR; } @@ -210,17 +207,17 @@ public void draw() { if ( enabled ) { switch ( mouseState ) { case MOUSE_OVER: - drawList( MOUSE_OVER_BORDER_COLOR, backgroundColor, scrollBarTrackColor ); + drawList( MOUSE_OVER_BORDER_COLOR, backgroundColor ); break; case MOUSE_DOWN: - drawList( MOUSE_OVER_BORDER_COLOR, backgroundColor, scrollBarTrackColor ); + drawList( MOUSE_OVER_BORDER_COLOR, backgroundColor ); break; default: - drawList( borderColor, backgroundColor, scrollBarTrackColor ); + drawList( borderColor, backgroundColor ); break; } } else { - drawList( DISABLED_BORDER_COLOR, DISABLED_LIST_CONTAINER_BACKGROUND_COLOR, DISABLED_SCROLL_BAR_TRACK_COLOR ); + drawList( DISABLED_BORDER_COLOR, DISABLED_LIST_CONTAINER_BACKGROUND_COLOR ); } drawBounds(); @@ -229,9 +226,9 @@ public void draw() { } - private void drawList( Color borderColor, Color containerColor, Color scrollBarTrackColor ) { + private void drawList( Color borderColor, Color containerColor ) { - engine.fillRectangle( scrollBar.bounds, scrollBarTrackColor ); + //engine.fillRectangle( scrollBar.bounds, scrollBarTrackColor ); engine.fillRectangle( bounds, containerColor ); engine.beginScissorMode( bounds ); @@ -351,24 +348,6 @@ protected double getItemTextHeight() { public boolean isMouseOutEntirely() { return mouseState == GuiComponentMouseState.MOUSE_OUT && scrollBar.mouseState == GuiComponentMouseState.MOUSE_OUT; } - - /** - * Obtém a cor do caminho da barra de rolagem. - * - * @return A cor do caminho da barra de rolagem. - */ - public Color getScrollBarTrackColor() { - return scrollBarTrackColor; - } - - /** - * Configura a cor do caminho da barra de rolagem. - * - * @param scrollBarTrackColor A cor do caminho da barra de rolagem. - */ - public void setScrollBarTrackColor( Color scrollBarTrackColor ) { - this.scrollBarTrackColor = scrollBarTrackColor; - } /** * Obtém a cor do fundo da barra de rolagem. @@ -424,24 +403,6 @@ public void setScrollBarTextColor( Color textColor ) { scrollBar.setTextColor( textColor ); } - /** - * Obtém a cor do preenchimento da barra de rolagem. - * - * @return A cor do preenchimento. - */ - public Color getScrollBarTrackFillColor() { - return scrollBar.getTrackFillColor(); - } - - /** - * Confira a cor do preenchimento da barra de rolagem. - * - * @param trackFillColor A cor do preenchimento. - */ - public void setScrollBarTrackFillColor( Color trackFillColor ) { - scrollBar.setTrackFillColor( trackFillColor ); - } - @Override public void move( double xAmount, double yAmount ) { bounds.x += xAmount; diff --git a/src/br/com/davidbuzatto/jsge/imgui/GuiScrollBar.java b/src/br/com/davidbuzatto/jsge/imgui/GuiScrollBar.java new file mode 100644 index 0000000..9f02167 --- /dev/null +++ b/src/br/com/davidbuzatto/jsge/imgui/GuiScrollBar.java @@ -0,0 +1,562 @@ +/* + * Copyright (C) 2025 Prof. Dr. David Buzatto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package br.com.davidbuzatto.jsge.imgui; + +import br.com.davidbuzatto.jsge.collision.CollisionUtils; +import br.com.davidbuzatto.jsge.core.engine.EngineFrame; +import br.com.davidbuzatto.jsge.geom.Rectangle; +import br.com.davidbuzatto.jsge.math.MathUtils; +import br.com.davidbuzatto.jsge.math.Vector2; +import java.awt.Color; + +/** + * Um componente de barra de rolagem. + * + * @author Prof. Dr. David Buzatto + */ +public class GuiScrollBar extends GuiComponent { + + public static final int HORIZONTAL = 1; + public static final int VERTICAL = 2; + private double value; + private double min; + private double max; + + protected GuiScrollBarButton scrollBarButton; + private int orientation; + private boolean showTrack; + + private boolean mouseWheelEnabled; + + /** + * Cria o componente. + * + * @param x Coordenada x do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param y Coordenada y do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param width Largura do retângulo que define os limites do componente. + * @param height Altura do retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + * @param engine A instância da engine utilizada para desenhar e atualizar + * o componente. + */ + public GuiScrollBar( double x, double y, double width, double height, double value, double min, double max, EngineFrame engine ) { + this( x, y, width, height, value, min, max, HORIZONTAL, engine ); + } + + /** + * Cria o componente. + * + * Essa versão do construtor depende da configuração "injetável" de uma + * instância de uma engine. + * @see br.com.davidbuzatto.jsge.core.engine.EngineFrame#useAsDependencyForIMGUI + * + * @param x Coordenada x do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param y Coordenada y do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param width Largura do retângulo que define os limites do componente. + * @param height Altura do retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + */ + public GuiScrollBar( double x, double y, double width, double height, double value, double min, double max ) { + this( x, y, width, height, value, min, max, HORIZONTAL ); + } + + /** + * Cria o componente. + * + * @param bounds Um retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + * @param engine A instância da engine utilizada para desenhar e atualizar + * o componente. + */ + public GuiScrollBar( Rectangle bounds, double value, double min, double max, EngineFrame engine ) { + this( bounds, value, min, max, HORIZONTAL, engine ); + } + + /** + * Cria o componente. + * + * Essa versão do construtor depende da configuração "injetável" de uma + * instância de uma engine. + * @see br.com.davidbuzatto.jsge.core.engine.EngineFrame#useAsDependencyForIMGUI + * + * @param bounds Um retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + */ + public GuiScrollBar( Rectangle bounds, double value, double min, double max ) { + this( bounds, value, min, max, HORIZONTAL ); + } + + /** + * Cria o componente. + * + * @param x Coordenada x do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param y Coordenada y do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param width Largura do retângulo que define os limites do componente. + * @param height Altura do retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + * @param orientation Se a barra de rolagem é horizontal ou vertical. + * @param engine A instância da engine utilizada para desenhar e atualizar + * o componente. + */ + public GuiScrollBar( double x, double y, double width, double height, double value, double min, double max, int orientation, EngineFrame engine ) { + super( x, y, width, height, engine ); + initData( value, min, max, orientation ); + initComponents( engine, SCROLL_BAR_BUTTON_SIZE ); + } + + /** + * Cria o componente. + * + * Essa versão do construtor depende da configuração "injetável" de uma + * instância de uma engine. + * @see br.com.davidbuzatto.jsge.core.engine.EngineFrame#useAsDependencyForIMGUI + * + * @param x Coordenada x do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param y Coordenada y do vértice superior esquerdo do retângulo que + * define os limites do componente. + * @param width Largura do retângulo que define os limites do componente. + * @param height Altura do retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + * @param orientation Se a barra de rolagem é horizontal ou vertical. + */ + public GuiScrollBar( double x, double y, double width, double height, double value, double min, double max, int orientation ) { + super( x, y, width, height ); + initData( value, min, max, orientation ); + initComponents( null, SCROLL_BAR_BUTTON_SIZE ); + } + + /** + * Cria o componente. + * + * @param bounds Um retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + * @param orientation Se a barra de rolagem é horizontal ou vertical. + * @param engine A instância da engine utilizada para desenhar e atualizar + * o componente. + */ + public GuiScrollBar( Rectangle bounds, double value, double min, double max, int orientation, EngineFrame engine ) { + super( bounds, engine ); + initData( value, min, max, orientation ); + initComponents( engine, SCROLL_BAR_BUTTON_SIZE ); + } + + /** + * Cria o componente. + * + * Essa versão do construtor depende da configuração "injetável" de uma + * instância de uma engine. + * @see br.com.davidbuzatto.jsge.core.engine.EngineFrame#useAsDependencyForIMGUI + * + * @param bounds Um retângulo que define os limites do componente. + * @param value O valor inicial do componente. + * @param min O valor mínimo do componente. + * @param max O valor máximo do componente. + * @param orientation Se a barra de rolagem é horizontal ou vertical. + */ + public GuiScrollBar( Rectangle bounds, double value, double min, double max, int orientation ) { + super( bounds ); + initData( value, min, max, orientation ); + initComponents( null, SCROLL_BAR_BUTTON_SIZE ); + } + + private void initData( double value, double min, double max, int orientation ) { + this.value = value; + this.min = min; + this.max = max; + this.orientation = orientation; + this.showTrack = true; + this.mouseWheelEnabled = true; + this.backgroundColor = SCROLL_BAR_TRACK_COLOR; + } + + private void initComponents( EngineFrame engine, double scrollBarButtonSize ) { + if ( engine == null ) { + if ( orientation == HORIZONTAL ) { + scrollBarButton = new GuiScrollBarButton( bounds.x, bounds.y, scrollBarButtonSize, bounds.height, scrollBarButtonSize, true ); + } else { + scrollBarButton = new GuiScrollBarButton( bounds.x, bounds.y, bounds.width, scrollBarButtonSize, scrollBarButtonSize, false ); + } + } else { + if ( orientation == HORIZONTAL ) { + scrollBarButton = new GuiScrollBarButton( bounds.x, bounds.y, scrollBarButtonSize, bounds.height, scrollBarButtonSize, true, engine ); + } else { + scrollBarButton = new GuiScrollBarButton( bounds.x, bounds.y, bounds.width, scrollBarButtonSize, scrollBarButtonSize, false, engine ); + } + } + updateScrollBarButtonPosition(); + } + + @Override + public void update( double delta ) { + + super.update( delta ); + + if ( visible && enabled ) { + + Vector2 mousePos = engine.getMousePositionPoint(); + scrollBarButton.update( delta, bounds ); + + if ( mouseWheelEnabled ) { + if ( mouseState == GuiComponentMouseState.MOUSE_OVER ) { + double mouseWheelMove = engine.getMouseWheelMove() * ( ( max - min ) / 10 ); + if ( min <= max ) { + setValue( getValue() + mouseWheelMove ); + } else { + setValue( getValue() - mouseWheelMove ); + } + } + } + + if ( mouseState == GuiComponentMouseState.MOUSE_DOWN && scrollBarButton.mouseState == GuiComponentMouseState.MOUSE_OUT ) { + if ( orientation == VERTICAL ) { + scrollBarButton.bounds.y = mousePos.y - SCROLL_BAR_BUTTON_SIZE / 2; + } else { + scrollBarButton.bounds.x = mousePos.x - SCROLL_BAR_BUTTON_SIZE / 2; + } + scrollBarButton.update( delta, bounds ); + } + + if ( orientation == VERTICAL ) { + + double maxScrollBarButtonY = bounds.y + scrollBarButton.bounds.height / 2; + double minScrollBarButtonY = bounds.y + bounds.height - scrollBarButton.bounds.height / 2; + double scrollBarButtonY = scrollBarButton.bounds.y + scrollBarButton.bounds.height / 2; + double percentage = MathUtils.inverseLerp( minScrollBarButtonY, maxScrollBarButtonY, scrollBarButtonY ); + + value = MathUtils.lerp( min, max, percentage ); + + } else { + + double minScrollBarButtonX = bounds.x + scrollBarButton.bounds.width / 2; + double maxScrollBarButtonX = bounds.x + bounds.width - scrollBarButton.bounds.width / 2; + double scrollBarButtonX = scrollBarButton.bounds.x + scrollBarButton.bounds.width / 2; + double percentage = MathUtils.inverseLerp( minScrollBarButtonX, maxScrollBarButtonX, scrollBarButtonX ); + + value = MathUtils.lerp( min, max, percentage ); + + } + + } + + } + + @Override + public void draw() { + + if ( visible ) { + + engine.setStrokeLineWidth( LINE_WIDTH ); + + if ( enabled ) { + switch ( mouseState ) { + case MOUSE_OVER: + drawScrollBar( SCROLL_BAR_TRACK_COLOR ); + break; + case MOUSE_DOWN: + drawScrollBar( SCROLL_BAR_TRACK_COLOR ); + break; + default: + drawScrollBar( SCROLL_BAR_TRACK_COLOR ); + break; + } + } else { + drawScrollBar( DISABLED_CONTAINER_BACKGROUND_COLOR ); + } + + drawBounds(); + + } + + } + + private void drawScrollBar( Color backgroundColor ) { + engine.fillRectangle( bounds, backgroundColor ); + scrollBarButton.draw(); + } + + private void updateScrollBarButtonPosition() { + + if ( orientation == VERTICAL ) { + + double maxScrollBarButtonY = bounds.y + scrollBarButton.bounds.height / 2; + double minScrollBarButtonY = bounds.y + bounds.height - scrollBarButton.bounds.height / 2; + double percentage = MathUtils.inverseLerp( min, max, value ); + + double scrollBarButtonY = MathUtils.lerp( minScrollBarButtonY, maxScrollBarButtonY, percentage ); + scrollBarButton.bounds.y = scrollBarButtonY - scrollBarButton.bounds.height / 2; + + } else { + + double minScrollBarButtonX = bounds.x + scrollBarButton.bounds.width / 2; + double maxScrollBarButtonX = bounds.x + bounds.width - scrollBarButton.bounds.width / 2; + double percentage = MathUtils.inverseLerp( min, max, value ); + + double scrollBarButtonX = MathUtils.lerp( minScrollBarButtonX, maxScrollBarButtonX, percentage ); + scrollBarButton.bounds.x = scrollBarButtonX - scrollBarButton.bounds.width / 2; + + } + + } + + @Override + public void setEnabled( boolean enabled ) { + super.setEnabled( enabled ); + scrollBarButton.setEnabled( enabled ); + } + + @Override + public void setVisible( boolean visible ) { + super.setVisible( visible ); + scrollBarButton.setVisible( visible ); + } + + /** + * Obtém o valor atual do componente. + * + * @return O valor atual. + */ + public double getValue() { + return value; + } + + /** + * Configura o valor do componente. + * + * @param value O valor do componente. + */ + public void setValue( double value ) { + if ( min <= max ) { + this.value = MathUtils.clamp( value, min, max ); + } else { + this.value = MathUtils.clamp( value, max, min ); + } + updateScrollBarButtonPosition(); + } + + /** + * Retorna o valor mínimo do componente. + * + * @return O valor mínimo. + */ + public double getMin() { + return min; + } + + /** + * Configura o valor mínimo do componente. + * + * @param min O valor mínimo do componente. + */ + public void setMin( double min ) { + this.min = min; + } + + /** + * Retorna o valor máximo do componente. + * + * @return O valor máximo. + */ + public double getMax() { + return max; + } + + /** + * Configura o valor máximo do componente. + * + * @param max O valor máximo do componente. + */ + public void setMax( double max ) { + this.max = max; + } + + /** + * Retorna se a trilha do componente está visível. + * + * @return Verdadeiro caso esteja visível, falso caso contrário. + */ + public boolean isShowTrack() { + return showTrack; + } + + /** + * Configura a visibilidade da trilha do componente. + * + * @param showTrack Verdeiro para exibir a trilha, falso para esconder. + */ + public void setShowTrack( boolean showTrack ) { + this.showTrack = showTrack; + } + + /** + * Retorna se o componente responde à rolagem da roda do mouse. + * + * @return Verdadeiro caso sim, falso caso contrário. + */ + public boolean isMouseWheelEnabled() { + return mouseWheelEnabled; + } + + /** + * Configura se o componente deve responder à rolagem da roda do mouse. + * + * @param mouseWheelEnabled Verdadeiro para responder, falso para não responder. + */ + public void setMouseWheelEnabled( boolean mouseWheelEnabled ) { + this.mouseWheelEnabled = mouseWheelEnabled; + } + + @Override + public void move( double xAmount, double yAmount ) { + bounds.x += xAmount; + bounds.y += yAmount; + scrollBarButton.bounds.x += xAmount; + scrollBarButton.bounds.y += yAmount; + } + + protected class GuiScrollBarButton extends GuiButton { + + private boolean dragging; + private Vector2 prevMousePos; + private final boolean moveHorizontally; + + public GuiScrollBarButton( double x, double y, double width, double height, double radius, boolean moveHorizontally, EngineFrame engine ) { + super( x, y, width, height, "", engine ); + this.moveHorizontally = moveHorizontally; + } + + public GuiScrollBarButton( double x, double y, double width, double height, double radius, boolean moveHorizontally ) { + super( x, y, width, height, "" ); + this.moveHorizontally = moveHorizontally; + } + + public void update( double delta, Rectangle containerBounds ) { + + if ( visible && enabled ) { + + Vector2 mousePos = engine.getMousePositionPoint(); + + if ( CollisionUtils.checkCollisionPointRectangle( mousePos, bounds ) ) { + mouseState = GuiComponentMouseState.MOUSE_OVER; + if ( engine.isMouseButtonPressed( EngineFrame.MOUSE_BUTTON_LEFT ) ) { + mouseState = GuiComponentMouseState.MOUSE_PRESSED; + } else if ( engine.isMouseButtonDown( EngineFrame.MOUSE_BUTTON_LEFT ) ) { + mouseState = GuiComponentMouseState.MOUSE_DOWN; + dragging = true; + } + } else { + mouseState = GuiComponentMouseState.MOUSE_OUT; + } + + if ( engine.isMouseButtonUp( EngineFrame.MOUSE_BUTTON_LEFT ) ) { + dragging = false; + } + + if ( dragging ) { + + mouseState = GuiComponentMouseState.MOUSE_DOWN; + + if ( moveHorizontally ) { + bounds.x += mousePos.x - prevMousePos.x; + if ( bounds.x + bounds.width > containerBounds.x + containerBounds.width ) { + bounds.x = containerBounds.x + containerBounds.width - bounds.width; + } else if ( bounds.x < containerBounds.x ) { + bounds.x = containerBounds.x; + } + } else { + bounds.y += mousePos.y - prevMousePos.y; + if ( bounds.y + bounds.height > containerBounds.y + containerBounds.height ) { + bounds.y = containerBounds.y + containerBounds.height - bounds.height; + } else if ( bounds.y < containerBounds.y ) { + bounds.y = containerBounds.y; + } + } + } + + prevMousePos = mousePos; + + } else { + mouseState = GuiComponentMouseState.MOUSE_OUT; + } + + } + + @Override + public void draw() { + + if ( visible ) { + + engine.setStrokeLineWidth( LINE_WIDTH ); + + if ( enabled ) { + + switch ( mouseState ) { + case MOUSE_OUT: + drawScrollBarButtonButton( backgroundColor, borderColor ); + break; + case MOUSE_OVER: + drawScrollBarButtonButton( MOUSE_OVER_BACKGROUND_COLOR, MOUSE_OVER_BORDER_COLOR ); + break; + case MOUSE_PRESSED: + drawScrollBarButtonButton( MOUSE_DOWN_BACKGROUND_COLOR, MOUSE_DOWN_BORDER_COLOR ); + break; + case MOUSE_DOWN: + drawScrollBarButtonButton( MOUSE_DOWN_BACKGROUND_COLOR, MOUSE_DOWN_BORDER_COLOR ); + break; + } + + } else { + drawScrollBarButtonButton( DISABLED_BACKGROUND_COLOR, DISABLED_BORDER_COLOR ); + } + + drawBounds(); + + } + + } + + private void drawScrollBarButtonButton( Color backgroundColor, Color borderColor ) { + if ( orientation == VERTICAL ) { + engine.fillRectangle( bounds, backgroundColor ); + } else { + engine.fillRectangle( bounds, backgroundColor ); + } + } + + } + +} diff --git a/src/br/com/davidbuzatto/jsge/imgui/GuiSlider.java b/src/br/com/davidbuzatto/jsge/imgui/GuiSlider.java index 7853b0a..9900973 100644 --- a/src/br/com/davidbuzatto/jsge/imgui/GuiSlider.java +++ b/src/br/com/davidbuzatto/jsge/imgui/GuiSlider.java @@ -288,10 +288,10 @@ public void draw() { if ( enabled ) { switch ( mouseState ) { case MOUSE_OVER: - drawSlider(CONTAINER_BACKGROUND_COLOR, MOUSE_OVER_BORDER_COLOR, MOUSE_DOWN_BACKGROUND_COLOR, 4 ); + drawSlider( CONTAINER_BACKGROUND_COLOR, MOUSE_OVER_BORDER_COLOR, MOUSE_DOWN_BACKGROUND_COLOR, 4 ); break; case MOUSE_DOWN: - drawSlider(CONTAINER_BACKGROUND_COLOR, MOUSE_DOWN_BORDER_COLOR, MOUSE_DOWN_BACKGROUND_COLOR, 4 ); + drawSlider( CONTAINER_BACKGROUND_COLOR, MOUSE_DOWN_BORDER_COLOR, MOUSE_DOWN_BACKGROUND_COLOR, 4 ); break; default: drawSlider( backgroundColor, borderColor, trackFillColor, 4 ); diff --git a/src/br/com/davidbuzatto/jsge/imgui/GuiTheme.java b/src/br/com/davidbuzatto/jsge/imgui/GuiTheme.java index 98b0ba7..4100923 100644 --- a/src/br/com/davidbuzatto/jsge/imgui/GuiTheme.java +++ b/src/br/com/davidbuzatto/jsge/imgui/GuiTheme.java @@ -155,7 +155,7 @@ public static GuiTheme buildLightTheme() { theme.listContainerBackgroundColor = new Color( 245, 245, 245 ); theme.disabledListContainerBackgroundColor = new Color( 245, 245, 245 ); - theme.scrollBarTrackColor = new Color( 220, 220, 220 ); + theme.scrollBarTrackColor = ColorUtils.colorBrightness( theme.backgroundColor, 0.4 ); theme.disabledScrollBarTrackColor = new Color( 220, 220, 220 ); theme.colorPickerDisabledOverlayColor = ColorUtils.fade( EngineFrame.LIGHTGRAY, 0.5 ); @@ -214,7 +214,7 @@ public static GuiTheme buildDarkTheme() { theme.listContainerBackgroundColor = new Color( 60, 63, 65 ); theme.disabledListContainerBackgroundColor = new Color( 121, 128, 132 ); - theme.scrollBarTrackColor = new Color( 180, 180, 180 ); + theme.scrollBarTrackColor = ColorUtils.colorBrightness( theme.backgroundColor, 0.4 ); theme.disabledScrollBarTrackColor = new Color( 180, 180, 180 ); theme.colorPickerDisabledOverlayColor = ColorUtils.fade( EngineFrame.LIGHTGRAY, 0.5 ); @@ -277,7 +277,7 @@ public static GuiTheme buildColoredTheme( Color color ) { theme.listContainerBackgroundColor = ColorUtils.colorBrightness( color, .3 ); theme.disabledListContainerBackgroundColor = ColorUtils.colorBrightness( cw, -.1 ); - theme.scrollBarTrackColor = ColorUtils.colorBrightness( cw, -.1 ); + theme.scrollBarTrackColor = ColorUtils.colorBrightness( theme.backgroundColor, 0.4 ); theme.disabledScrollBarTrackColor = ColorUtils.colorBrightness( cw, -.1 ); theme.colorPickerDisabledOverlayColor = ColorUtils.fade( EngineFrame.LIGHTGRAY, 0.5 ); @@ -424,7 +424,6 @@ public void apply( GuiComponent component ) { c.setTextColor( containerTextColor ); } else if ( component instanceof GuiList c ) { c.setBackgroundColor( listContainerBackgroundColor ); - c.setScrollBarTrackColor( scrollBarTrackColor ); apply( c.scrollBar ); } else if ( component instanceof GuiPanel c ) { c.setBackgroundColor( containerBackgroundColor ); @@ -438,6 +437,9 @@ public void apply( GuiComponent component ) { c.setBackgroundColor( containerBackgroundColor ); c.setTrackFillColor( mouseOverBackgroundColor ); apply( c.sliderButton ); + } else if ( component instanceof GuiScrollBar c ) { + c.setBackgroundColor( scrollBarTrackColor ); + apply(c.scrollBarButton ); } else if ( component instanceof GuiSpinner c ) { c.setBackgroundColor( containerBackgroundColor ); apply( c.leftButton );