001/* 002 * ============================================================================ 003 * Copyright © 2002-2024 by Thomas Thrien. 004 * All Rights Reserved. 005 * ============================================================================ 006 * Licensed to the public under the agreements of the GNU Lesser General Public 007 * License, version 3.0 (the "License"). You may obtain a copy of the License at 008 * 009 * http://www.gnu.org/licenses/lgpl.html 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 014 * License for the specific language governing permissions and limitations 015 * under the License. 016 */ 017 018package org.tquadrat.foundation.fx.control.tester; 019 020import static java.lang.String.format; 021import static java.lang.System.err; 022import static java.lang.System.out; 023import static javafx.beans.binding.Bindings.createStringBinding; 024import static javafx.scene.layout.Region.USE_COMPUTED_SIZE; 025import static org.apiguardian.api.API.Status.EXPERIMENTAL; 026 027import java.time.OffsetDateTime; 028 029import org.apiguardian.api.API; 030import org.tquadrat.foundation.annotation.ClassVersion; 031import org.tquadrat.foundation.annotation.ProgramClass; 032import org.tquadrat.foundation.fx.control.TimeSlider; 033import org.tquadrat.foundation.fx.control.TimeSlider.Granularity; 034import javafx.application.Application; 035import javafx.geometry.Insets; 036import javafx.scene.Scene; 037import javafx.scene.control.DatePicker; 038import javafx.scene.control.TextField; 039import javafx.scene.layout.HBox; 040import javafx.scene.layout.Pane; 041import javafx.scene.layout.VBox; 042import javafx.stage.Stage; 043 044/** 045 * Test bed for the custom control 046 * {@link TimeSlider}. 047 * 048 * @extauthor Thomas Thrien - thomas.thrien@tquadrat.org 049 * @version $Id: TimeSliderTester.java 1121 2024-03-16 16:51:23Z tquadrat $ 050 * @since 0.4.6 051 * 052 * @UMLGraph.link 053 */ 054@SuppressWarnings( "UseOfSystemOutOrSystemErr" ) 055@ClassVersion( sourceVersion = "$Id: TimeSliderTester.java 1121 2024-03-16 16:51:23Z tquadrat $" ) 056@API( status = EXPERIMENTAL, since = "0.4.6" ) 057@ProgramClass 058public final class TimeSliderTester extends Application 059{ 060 /*------------*\ 061 ====** Attributes **======================================================= 062 \*------------*/ 063 /** 064 * The spacing. 065 */ 066 private final double m_Spacing = 7.5; 067 068 /*------------------------*\ 069 ====** Static Initialisations **=========================================== 070 \*------------------------*/ 071 /** 072 * The flag that tracks the assertion on/off status for this package. 073 */ 074 private static boolean m_AssertionOn; 075 076 static 077 { 078 //---* Determine the assertion status *-------------------------------- 079 m_AssertionOn = false; 080 //noinspection AssertWithSideEffects,PointlessBooleanExpression,NestedAssignment 081 assert (m_AssertionOn = true) == true : "Assertion is switched off"; 082 } 083 084 /*--------------*\ 085 ====** Constructors **===================================================== 086 \*--------------*/ 087 /** 088 * Creates a new instance of {@code TimeSliderTester}. 089 */ 090 public TimeSliderTester() { /* Just exists */ } 091 092 /*---------*\ 093 ====** Methods **========================================================== 094 \*---------*/ 095 /** 096 * Creates an advanced 097 * {@link TimeSlider}. 098 * 099 * @param root The parent node. 100 */ 101 private final void createAdvancedTimeSlider( final Pane root ) 102 { 103 final var lowValue = OffsetDateTime.now() 104 .withHour( 8 ) 105 .withMinute( 0 ) 106 .withSecond( 0 ) 107 .withNano( 0 ) 108 .toOffsetTime(); 109 final var highValue = OffsetDateTime.now() 110 .withHour( 17 ) 111 .withMinute( 0 ) 112 .withSecond( 0 ) 113 .withNano( 0 ) 114 .toOffsetTime(); 115 116 final var paramBox = new HBox(); 117 paramBox.setSpacing( m_Spacing ); 118 paramBox.setPadding( new Insets( m_Spacing ) ); 119 root.getChildren().add( paramBox ); 120 final var min = new TextField(); 121 final var max = new TextField(); 122 paramBox.getChildren().addAll( min, max ); 123 124 final var sliderBox = new HBox(); 125 sliderBox.setSpacing( m_Spacing ); 126 sliderBox.setPadding( new Insets( m_Spacing ) ); 127 root.getChildren().add( sliderBox ); 128 129 final var timeSlider = new TimeSlider(); 130 131 timeSlider.setLowValue( lowValue ); 132 timeSlider.setHighValue( highValue ); 133 timeSlider.setGranularity( Granularity.ONE_HOUR ); 134 135 timeSlider.setMinWidth( 600.0 ); 136 timeSlider.setPrefWidth( USE_COMPUTED_SIZE ); 137 timeSlider.setMaxWidth( Double.MAX_VALUE ); 138 sliderBox.getChildren().add( timeSlider ); 139 min.textProperty().set( format( "%s", timeSlider.getMin() ) ); 140 max.textProperty().set( format( "%s", timeSlider.getMax() ) ); 141 142 final var fieldBox = new HBox(); 143 fieldBox.setSpacing( m_Spacing ); 144 fieldBox.setPadding( new Insets( m_Spacing ) ); 145 root.getChildren().add( fieldBox ); 146 147 final var low = new TextField(); 148 final var lowValueBinding = createStringBinding( () -> format( "%s", timeSlider.getLowValue() ), timeSlider.lowValueProperty() ); 149 low.textProperty().bind( lowValueBinding ); 150 final var range = new TextField(); 151 final var durationBinding = createStringBinding( () -> format( "%s", timeSlider.getDuration() ), timeSlider.durationProperty() ); 152 range.textProperty().bind( durationBinding ); 153 final var high = new TextField(); 154 final var highValueBinding = createStringBinding( () -> format( "%s", timeSlider.getHighValue() ), timeSlider.highValueProperty() ); 155 high.textProperty().bind( highValueBinding ); 156 fieldBox.getChildren().addAll( low, range, high ); 157 } // createAdvancedTimeSlider() 158 159 /** 160 * Creates a 161 * {@link TimeSlider}. 162 * 163 * @param root The parent node. 164 */ 165 private final void createDateChangingTimeSlider( final Pane root ) 166 { 167 final var lowValue = OffsetDateTime.now() 168 .withHour( 8 ) 169 .withMinute( 0 ) 170 .withSecond( 0 ) 171 .withNano( 0 ) 172 .toOffsetTime(); 173 final var highValue = OffsetDateTime.now() 174 .withHour( 17 ) 175 .withMinute( 0 ) 176 .withSecond( 0 ) 177 .withNano( 0 ) 178 .toOffsetTime(); 179 180 final var paramBox = new HBox(); 181 paramBox.setSpacing( m_Spacing ); 182 paramBox.setPadding( new Insets( m_Spacing ) ); 183 root.getChildren().add( paramBox ); 184 final var date = new DatePicker(); 185 final var min = new TextField(); 186 final var max = new TextField(); 187 paramBox.getChildren().addAll( date, min, max ); 188 189 final var sliderBox = new HBox(); 190 sliderBox.setSpacing( m_Spacing ); 191 sliderBox.setPadding( new Insets( m_Spacing ) ); 192 root.getChildren().add( sliderBox ); 193 194 final var timeSlider = new TimeSlider(); 195 196 timeSlider.setLowValue( lowValue ); 197 timeSlider.setHighValue( highValue ); 198 timeSlider.setGranularity( Granularity.ONE_HOUR ); 199 200 timeSlider.setMinWidth( 600.0 ); 201 timeSlider.setPrefWidth( USE_COMPUTED_SIZE ); 202 timeSlider.setMaxWidth( Double.MAX_VALUE ); 203 sliderBox.getChildren().add( timeSlider ); 204 date.valueProperty().bindBidirectional( timeSlider.dayProperty() ); 205 min.textProperty().set( format( "%s", timeSlider.getMin() ) ); 206 max.textProperty().set( format( "%s", timeSlider.getMax() ) ); 207 208 final var fieldBox = new HBox(); 209 fieldBox.setSpacing( m_Spacing ); 210 fieldBox.setPadding( new Insets( m_Spacing ) ); 211 root.getChildren().add( fieldBox ); 212 213 final var low = new TextField(); 214 final var lowValueBinding = createStringBinding( () -> format( "%s", timeSlider.getLowValue() ), timeSlider.lowValueProperty() ); 215 low.textProperty().bind( lowValueBinding ); 216 final var range = new TextField(); 217 final var durationBinding = createStringBinding( () -> format( "%s", timeSlider.getDuration() ), timeSlider.durationProperty() ); 218 range.textProperty().bind( durationBinding ); 219 final var high = new TextField(); 220 final var highValueBinding = createStringBinding( () -> format( "%s", timeSlider.getHighValue() ), timeSlider.highValueProperty() ); 221 high.textProperty().bind( highValueBinding ); 222 fieldBox.getChildren().addAll( low, range, high ); 223 } // createDateChangingTimeSlider() 224 225 /** 226 * Creates a simple 227 * {@link TimeSlider}. 228 * 229 * @param root The parent node. 230 */ 231 private final void createDefaultTimeSlider( final Pane root ) 232 { 233 final var paramBox = new HBox(); 234 paramBox.setSpacing( m_Spacing ); 235 paramBox.setPadding( new Insets( m_Spacing ) ); 236 root.getChildren().add( paramBox ); 237 final var min = new TextField(); 238 final var max = new TextField(); 239 paramBox.getChildren().addAll( min, max ); 240 241 final var sliderBox = new HBox(); 242 sliderBox.setSpacing( m_Spacing ); 243 sliderBox.setPadding( new Insets( m_Spacing ) ); 244 root.getChildren().add( sliderBox ); 245 246 final var timeSlider = new TimeSlider(); 247 248 timeSlider.setMinWidth( 600.0 ); 249 timeSlider.setPrefWidth( USE_COMPUTED_SIZE ); 250 timeSlider.setMaxWidth( Double.MAX_VALUE ); 251 sliderBox.getChildren().add( timeSlider ); 252 min.textProperty().set( format( "%s", timeSlider.getMin() ) ); 253 max.textProperty().set( format( "%s", timeSlider.getMax() ) ); 254 255 final var fieldBox = new HBox(); 256 fieldBox.setSpacing( m_Spacing ); 257 fieldBox.setPadding( new Insets( m_Spacing ) ); 258 root.getChildren().add( fieldBox ); 259 260 final var low = new TextField(); 261 final var lowValueBinding = createStringBinding( () -> format( "%s", timeSlider.getLowValue() ), timeSlider.lowValueProperty() ); 262 low.textProperty().bind( lowValueBinding ); 263 final var range = new TextField(); 264 final var durationBinding = createStringBinding( () -> format( "%s", timeSlider.getDuration() ), timeSlider.durationProperty() ); 265 range.textProperty().bind( durationBinding ); 266 final var high = new TextField(); 267 final var highValueBinding = createStringBinding( () -> format( "%s", timeSlider.getHighValue() ), timeSlider.highValueProperty() ); 268 high.textProperty().bind( highValueBinding ); 269 fieldBox.getChildren().addAll( low, range, high ); 270 } // createSimpleTimeSlider() 271 272 /** 273 * The program entry point. 274 * 275 * @param args The command line arguments. 276 */ 277 public static final void main( final String... args ) 278 { 279 out.printf( "Assertion is %s%n".formatted( m_AssertionOn ? "ON" : "OFF" ) ); 280 281 try 282 { 283 launch( args ); 284 } 285 catch( final Throwable t ) 286 { 287 t.printStackTrace( err ); 288 } 289 } // main() 290 291 /** 292 * {@inheritDoc} 293 */ 294 @SuppressWarnings( "ProhibitedExceptionDeclared" ) 295 @Override 296 public void start( final Stage primaryStage ) throws Exception 297 { 298 //---* Compose the scene *--------------------------------------------- 299 final var root = new VBox(); 300 301 createDefaultTimeSlider( root ); 302 createAdvancedTimeSlider( root ); 303 createDateChangingTimeSlider( root ); 304 305 final var scene = new Scene( root, -1, -1 ); 306 primaryStage.setScene( scene ); 307 primaryStage.centerOnScreen(); 308 primaryStage.setOnCloseRequest( $ -> out.println( "Done!" ) ); 309 310 //---* Show the stage *-------------------------------------------- 311 primaryStage.show(); 312 } // start() 313} 314// class TimeSliderTester 315 316/* 317 * End of File 318 */