├── gradle.properties ├── screen.png ├── .gitignore ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src └── main │ ├── resources │ ├── jpro.conf │ └── com │ │ └── dlsc │ │ └── jpro │ │ └── calendar │ │ ├── icons │ │ ├── clear-search-icon.png │ │ ├── clear-search-icon@2x.png │ │ └── clear-search-icon@3x.png │ │ └── calendar.css │ └── java │ └── com │ └── dlsc │ └── jpro │ └── calendar │ ├── CalendarJProMain.java │ ├── CalendarToolBar.java │ ├── CalendarViewSkin.java │ └── CalendarView.java ├── README.md ├── gradlew.bat ├── gradlew └── LICENSE /gradle.properties: -------------------------------------------------------------------------------- 1 | JPRO_PLUGIN_VERSION = 2020.1.0-RC1 2 | JPRO_VERSION = 2020.1.0-RC1 -------------------------------------------------------------------------------- /screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlemmermann/JProCalendarFX/HEAD/screen.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.gradle 2 | /.idea 3 | /build 4 | /out 5 | /tmp 6 | /logs 7 | RUNNING_PID -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlemmermann/JProCalendarFX/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/jpro.conf: -------------------------------------------------------------------------------- 1 | 2 | //jpro apps 3 | jpro.applications { 4 | "jprocalendar" = com.dlsc.jpro.calendar.CalendarJProMain 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/main/resources/com/dlsc/jpro/calendar/icons/clear-search-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlemmermann/JProCalendarFX/HEAD/src/main/resources/com/dlsc/jpro/calendar/icons/clear-search-icon.png -------------------------------------------------------------------------------- /src/main/resources/com/dlsc/jpro/calendar/icons/clear-search-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlemmermann/JProCalendarFX/HEAD/src/main/resources/com/dlsc/jpro/calendar/icons/clear-search-icon@2x.png -------------------------------------------------------------------------------- /src/main/resources/com/dlsc/jpro/calendar/icons/clear-search-icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dlemmermann/JProCalendarFX/HEAD/src/main/resources/com/dlsc/jpro/calendar/icons/clear-search-icon@3x.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [JPro](https://www.jpro.one/) can be used to run JavaFX in the browser. 3 | 4 | This application can be viewed here: https://demos.jpro.one/calendar.html 5 | 6 | ![alt text](screen.png "Screenshot") 7 | 8 | 9 | # How to start JProCalendarFX # 10 | 11 | 12 | ## Web Browser ## 13 | 14 | ### Start JPro in foreground (development mode) ### 15 | 16 | ``` 17 | gradle jproRun 18 | ``` 19 | 20 | 21 | ### Start JPro in background (server mode) ### 22 | 23 | ``` 24 | gradle jproRestart 25 | ``` 26 | 27 | 28 | ### Open JPro app in Web Browser ### 29 | ``` 30 | http://localhost:8080/index.html 31 | ``` 32 | 33 | ### Show all JPro apps in Browser #### 34 | ``` 35 | http://localhost:8080/test/default 36 | ``` 37 | 38 | ### Open JPro app in fullscreen #### 39 | ``` 40 | http://localhost:8080/test/fullscreen/[app-name] 41 | ``` 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/java/com/dlsc/jpro/calendar/CalendarJProMain.java: -------------------------------------------------------------------------------- 1 | package com.dlsc.jpro.calendar; 2 | 3 | import com.calendarfx.model.Calendar; 4 | import com.calendarfx.model.Calendar.Style; 5 | import com.calendarfx.model.CalendarSource; 6 | import com.calendarfx.util.CalendarFX; 7 | import javafx.application.Application; 8 | import javafx.scene.Scene; 9 | import javafx.scene.layout.BorderPane; 10 | import javafx.stage.Stage; 11 | 12 | public class CalendarJProMain extends Application 13 | { 14 | public static void main(String[] args) 15 | { 16 | launch(args); 17 | } 18 | 19 | @Override 20 | 21 | public void start(Stage stage) { 22 | 23 | CalendarView calendarView = new CalendarView(); 24 | 25 | Calendar dirk = new Calendar("Dirk"); 26 | Calendar katja = new Calendar("Katja"); 27 | Calendar philip = new Calendar("Philip"); 28 | Calendar jule = new Calendar("Jule"); 29 | Calendar armin = new Calendar("Armin"); 30 | 31 | dirk.setStyle(Style.STYLE1); 32 | katja.setStyle(Style.STYLE2); 33 | philip.setStyle(Style.STYLE3); 34 | jule.setStyle(Style.STYLE4); 35 | armin.setStyle(Style.STYLE5); 36 | 37 | CalendarSource family = new CalendarSource("Family"); 38 | family.getCalendars().setAll(dirk, katja, philip, jule, armin); 39 | 40 | Calendar n471 = new Calendar("N 470"); 41 | Calendar n788 = new Calendar("N 788"); 42 | Calendar n904 = new Calendar("N 904"); 43 | 44 | n471.setStyle(Style.STYLE6); 45 | n788.setStyle(Style.STYLE7); 46 | n904.setStyle(Style.STYLE1); 47 | 48 | CalendarSource projects = new CalendarSource("Projects"); 49 | projects.getCalendars().setAll(n471, n788, n904); 50 | 51 | calendarView.getCalendarSources().setAll(family, projects); 52 | 53 | BorderPane borderPane = new BorderPane(); 54 | borderPane.setTop(new CalendarToolBar(calendarView)); 55 | borderPane.setCenter(calendarView); 56 | 57 | Scene scene = new Scene(borderPane); 58 | scene.getStylesheets().add(CalendarView.class.getResource("calendar.css").toExternalForm()); 59 | 60 | stage.setTitle("Hello jpro!"); 61 | stage.setScene(scene); 62 | stage.sizeToScene(); 63 | 64 | //open JavaFX window 65 | stage.show(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/dlsc/jpro/calendar/CalendarToolBar.java: -------------------------------------------------------------------------------- 1 | package com.dlsc.jpro.calendar; 2 | 3 | import com.calendarfx.view.SearchResultView; 4 | import javafx.scene.control.Button; 5 | import javafx.scene.control.ToggleButton; 6 | import javafx.scene.control.ToggleGroup; 7 | import javafx.scene.layout.HBox; 8 | import javafx.scene.layout.Priority; 9 | import org.controlsfx.control.textfield.CustomTextField; 10 | 11 | /** 12 | * Created by lemmi on 29.08.17. 13 | */ 14 | public class CalendarToolBar extends HBox{ 15 | 16 | private final CalendarView calendarView; 17 | 18 | public CalendarToolBar(CalendarView calendarView) { 19 | this.calendarView = calendarView; 20 | 21 | getStyleClass().addAll("module-toolbar", "calendar-toolbar", "primary-color-calendar"); 22 | 23 | ToggleGroup group = new ToggleGroup(); 24 | 25 | ToggleButton showDay = new ToggleButton("DAY"); 26 | ToggleButton showWeek = new ToggleButton("WEEK"); 27 | ToggleButton showMonth = new ToggleButton("MONTH"); 28 | //ToggleButton showYear = new ToggleButton("YEAR"); 29 | 30 | showDay.setOnAction(evt -> showDayPage()); 31 | showWeek.setOnAction(evt -> showWeekPage()); 32 | showMonth.setOnAction(evt -> showMonthPage()); 33 | //showYear.setOnAction(evt -> showYearPage()); 34 | 35 | showDay.getStyleClass().add("first"); 36 | showMonth.getStyleClass().add("last"); 37 | 38 | showDay.setSelected(true); 39 | showDay.setMaxHeight(Double.MAX_VALUE); 40 | showWeek.setMaxHeight(Double.MAX_VALUE); 41 | showMonth.setMaxHeight(Double.MAX_VALUE); 42 | //showYear.setMaxHeight(Double.MAX_VALUE); 43 | 44 | group.getToggles().addAll(showDay, showWeek, showMonth/*, showYear*/); 45 | 46 | HBox switcher = new HBox(showDay, showWeek, showMonth/*, showYear*/); 47 | switcher.getStyleClass().add("switcher"); 48 | switcher.setFillHeight(true); 49 | switcher.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); 50 | HBox.setHgrow(switcher, Priority.ALWAYS); 51 | 52 | CustomTextField searchField = new CustomTextField(); 53 | Button clearSearchButton = new Button(); 54 | clearSearchButton.getStyleClass().add("clear-search"); 55 | clearSearchButton.setOnAction(evt -> searchField.setText("")); 56 | searchField.setRight(clearSearchButton); 57 | searchField.setPromptText("SEARCH"); 58 | searchField.setPrefColumnCount(30); 59 | 60 | SearchResultView searchResultView = calendarView.getSearchResultView(); 61 | searchResultView.searchTextProperty().bind(searchField.textProperty()); 62 | 63 | getChildren().addAll(switcher, searchField); 64 | setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE); 65 | } 66 | 67 | private void showDayPage() { 68 | calendarView.showDayPage(); 69 | } 70 | 71 | private void showWeekPage() { 72 | calendarView.showWeekPage(); 73 | } 74 | 75 | private void showMonthPage() { 76 | calendarView.showMonthPage(); 77 | } 78 | 79 | private void showYearPage() { 80 | calendarView.showYearPage(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | 88 | @rem Execute Gradle 89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 90 | 91 | :end 92 | @rem End local scope for the variables with windows NT shell 93 | if "%ERRORLEVEL%"=="0" goto mainEnd 94 | 95 | :fail 96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 97 | rem the _cmd.exe /c_ return code! 98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 99 | exit /b 1 100 | 101 | :mainEnd 102 | if "%OS%"=="Windows_NT" endlocal 103 | 104 | :omega 105 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /src/main/resources/com/dlsc/jpro/calendar/calendar.css: -------------------------------------------------------------------------------- 1 | .root { 2 | -fx-font-family: "Rubik Medium"; 3 | -fx-font-size: 13; 4 | -toolbar-text-fill: white; 5 | -toolbar-background-color: rgb(43, 43, 43); 6 | -toolbar-button-pressed-color: rgba(255, 255, 255, .4); 7 | -toolbar-button-selected-color: rgba(255, 255, 255, .1); 8 | 9 | -drop-shadow-1: dropshadow(gaussian, rgba(0, 0, 0, .26), 10, 0.12, -1, 2); 10 | -drop-shadow-2: dropshadow(gaussian, rgba(0, 0, 0, .26), 15, 0.16, -1, 4); 11 | -drop-shadow-3: dropshadow(gaussian, rgba(0, 0, 0, .26), 20, 0.19, -1, 6); 12 | 13 | -slate-green: #63946a; 14 | -greyish-brown: #4a4a4a; 15 | -yellowish-orange: #ffa208; 16 | -greyish-brown-two: #595959; 17 | -vivid-purple: #9012fe; 18 | -tomato: #e94b35; 19 | -charcoal-grey: #3b424c; 20 | -steel: #7a8390; 21 | -white: #ebebeb; 22 | -greyish: #a3a3a3; 23 | -white-two: #f6f6f4; 24 | -white-three: #fbfbfb; 25 | -white-four: #ffffff; 26 | } 27 | 28 | /* ---------------------------------------------------------------------------- 29 | * Module toolbar. 30 | */ 31 | .module-toolbar { 32 | -fx-spacing: 0; 33 | -fx-padding: 0 20 0 0; 34 | -fx-fill-height: true; 35 | -fx-alignment: center-left; 36 | -fx-pref-height: 60; 37 | } 38 | 39 | .module-toolbar .buttons { 40 | -fx-spacing: 10; 41 | -fx-fill-height: true; 42 | -fx-alignment: center; 43 | -fx-padding: 0 15 0 0; 44 | } 45 | 46 | .module-toolbar .separator:vertical .line { 47 | -fx-border-color: rgba(255, 255, 255, .2); 48 | -fx-border-width: 1; 49 | } 50 | 51 | .module-toolbar .text-field { 52 | -fx-background-color: rgba(0, 0, 0, .2); 53 | -fx-background-radius: 1000; 54 | -fx-text-fill: white; 55 | -fx-padding: 8 8 8 16; 56 | } 57 | 58 | .module-toolbar .text-field .clear-search { 59 | -fx-background-color: transparent; 60 | -fx-padding: 0; 61 | -fx-graphic: url("icons/clear-search-icon.png"); 62 | } 63 | 64 | .module-toolbar .controls { 65 | -fx-alignment: center-left; 66 | -fx-padding: 5 10 0 10; 67 | } 68 | 69 | .module-toolbar .close-button, 70 | .module-toolbar .minimize-button, 71 | .module-toolbar .search-button { 72 | -fx-background-color: transparent; 73 | } 74 | 75 | .scroll-bar { 76 | -fx-background-color: transparent; 77 | -fx-padding: 2; 78 | } 79 | 80 | .scroll-bar:vertical .decrement-button, 81 | .scroll-bar:vertical .increment-button, 82 | .scroll-bar:vertical .decrement-arrow, 83 | .scroll-bar:vertical .increment-arrow { 84 | -fx-pref-height: 0; 85 | -fx-pref-width: 8; 86 | } 87 | 88 | .scroll-bar:horizontal .decrement-button, 89 | .scroll-bar:horizontal .increment-button, 90 | .scroll-bar:horizontal .decrement-arrow, 91 | .scroll-bar:horizontal .increment-arrow { 92 | -fx-pref-height: 8; 93 | -fx-pref-width: 0; 94 | } 95 | 96 | .scroll-bar .thumb { 97 | -fx-background-color: rgba(0, 0, 0, .2); 98 | -fx-background-insets: 0 0 0 2; 99 | -fx-background-radius: 12; 100 | -fx-border-width: 0; 101 | -fx-border-insets: 0; 102 | -fx-padding: 0; 103 | } 104 | 105 | .primary-color-calendar { 106 | -fx-background-color: -slate-green !important; 107 | } 108 | 109 | .calendar-toolbar { 110 | } 111 | 112 | .calendar-toolbar .text-field { 113 | -fx-prompt-text-fill: derive(-slate-green, 20%); 114 | } 115 | 116 | .calendar-toolbar .switcher { 117 | -fx-padding: 15; 118 | } 119 | 120 | .calendar-toolbar .toggle-button { 121 | -fx-background-color: rgba(0, 0, 0, .2); 122 | -fx-background-radius: 0; 123 | -fx-text-fill: derive(-slate-green, 20%); 124 | -fx-padding: 10 20 10 20; 125 | } 126 | 127 | .calendar-toolbar .toggle-button:selected { 128 | -fx-text-fill: white; 129 | -fx-background-color: rgba(255, 255, 255, .2); 130 | } 131 | 132 | .calendar-toolbar .toggle-button.first { 133 | -fx-background-radius: 4 0 0 4 !important; 134 | } 135 | 136 | .calendar-toolbar .toggle-button.last { 137 | -fx-background-radius: 0 4 4 0 !important; 138 | } 139 | 140 | .calendar-view .scroll-pane { 141 | -fx-background-color: white; 142 | } 143 | 144 | .calendar-page { 145 | -fx-background-color: -white-two !important; 146 | } 147 | 148 | .source-view { 149 | -fx-background-color: white !important; 150 | } 151 | 152 | #date-picker { 153 | -fx-background-color: white !important; 154 | } 155 | 156 | .calendar-page > .container > .header { 157 | -fx-padding: 30; 158 | } 159 | 160 | .calendar-page > .container > .header > .date-text { 161 | -fx-font-family: "Rubik Light"; 162 | -fx-font-size: 2.2em; 163 | } 164 | 165 | .calendar-page .navigation-button-bar .button { 166 | -fx-background-color: linear-gradient(to bottom, -white-four, -white-two) !important; 167 | -fx-border-color: lightgray !important; 168 | -fx-text-fill: -slate-green !important; 169 | -fx-padding: 10 20 10 20 !important; 170 | } 171 | 172 | .calendar-page .navigation-button-bar .previous-date-button { 173 | -fx-text-fill: gray !important; 174 | -fx-background-radius: 4 0 0 4; 175 | -fx-border-radius: 4 0 0 4; 176 | -fx-border-width: 1 0 1 1; 177 | } 178 | 179 | .calendar-page .navigation-button-bar .next-date-button { 180 | -fx-text-fill: gray !important; 181 | -fx-background-radius: 0 4 4 0; 182 | -fx-border-radius: 0 4 4 0; 183 | -fx-border-width: 1 1 1 0; 184 | } 185 | 186 | /* ---------------------------------------------------------------------------- 187 | * Month Calendar. 188 | */ 189 | 190 | #date-picker { 191 | 192 | } 193 | 194 | #date-picker .day-of-week-label { 195 | -fx-border-color: transparent; 196 | -fx-text-fill: -greyish; 197 | } 198 | 199 | #date-picker .month-day { 200 | -fx-text-fill: gray; 201 | -fx-padding: 10; 202 | -fx-font-size: 14px; 203 | } 204 | 205 | #date-picker .day-not-of-month-label { 206 | -fx-text-fill: transparent; 207 | } 208 | 209 | #date-picker .selected-month-date { 210 | -fx-background-color: rgba(238, 238, 238); 211 | -fx-background-radius: 1000; 212 | -fx-text-fill: black; 213 | -fx-font-weight: bold; 214 | } 215 | 216 | #date-picker .weekend-day { 217 | -fx-background-color: white; 218 | } 219 | 220 | #date-picker .month-label { 221 | -fx-font-size: 15; 222 | -fx-text-fill: -greyish-brown-two; 223 | } 224 | 225 | #date-picker .year-label { 226 | -fx-font-size: 15; 227 | -fx-text-fill: -greyish-brown-two; 228 | } 229 | 230 | #date-picker .container { 231 | -fx-padding: 20 ; 232 | } 233 | 234 | #date-picker .previous-button, 235 | #date-picker .next-button, 236 | #date-picker .previous-button, 237 | #date-picker .next-button { 238 | -fx-background-color: -greyish-brown-two; 239 | -fx-pref-width: 8.0; 240 | -fx-pref-height: 8.0; 241 | -fx-max-width: 8.0; 242 | -fx-max-height: 8.0; 243 | } 244 | 245 | #date-picker .previous-button:hover, 246 | #date-picker .next-button:hover, 247 | #date-picker .previous-button:hover, 248 | #date-picker .next-button:hover { 249 | -fx-background-color: lightgray; 250 | } 251 | 252 | #date-picker .previous-button:pressed, 253 | #date-picker .next-button:pressed, 254 | #date-picker .previous-button:pressed, 255 | #date-picker .next-button:pressed { 256 | -fx-background-color: gray; 257 | } 258 | 259 | #date-picker .previous-button, 260 | #date-picker .previous-button { 261 | -fx-shape: "M3,0 V3 L0 1.5 L3,0 Z"; 262 | } 263 | 264 | #date-picker .next-button, 265 | #date-picker .next-button { 266 | -fx-shape: "M0,0 L3 1.5 L0,3 V0 Z"; 267 | } 268 | 269 | /* ---------------------------------------------------------------------------- 270 | * Source view. 271 | */ 272 | 273 | .source-view .text { 274 | -fx-text-fill: -charcoal-grey; 275 | -fx-font-family: "Rubik Regular"; 276 | -fx-font-size: 14px; 277 | } 278 | 279 | /* ---------------------------------------------------------------------------- 280 | * Search result view. 281 | */ 282 | 283 | .search-result-view .list-cell { 284 | -fx-background-color: -white-four; 285 | -fx-padding: 10; 286 | } 287 | 288 | .search-result-view .list-cell .label { 289 | -fx-font-size: 14 !important; 290 | } 291 | 292 | .search-result-view .list-cell .container { 293 | -fx-padding: 0 0 30 0; 294 | } 295 | 296 | 297 | -------------------------------------------------------------------------------- /src/main/java/com/dlsc/jpro/calendar/CalendarViewSkin.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015, 2016 Dirk Lemmermann Software & Consulting (dlsc.com) 3 | *

4 | * This file is part of CalendarFX. 5 | */ 6 | 7 | package com.dlsc.jpro.calendar; 8 | 9 | import com.calendarfx.model.Entry; 10 | import com.calendarfx.view.CalendarFXControl; 11 | import com.calendarfx.view.DeveloperConsole; 12 | import com.calendarfx.view.SearchResultView; 13 | import com.calendarfx.view.SourceView; 14 | import com.calendarfx.view.YearMonthView; 15 | import com.calendarfx.view.page.DayPage; 16 | import com.calendarfx.view.page.PageBase; 17 | import com.calendarfx.view.print.PrintView; 18 | import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon; 19 | import de.jensd.fx.glyphs.fontawesome.utils.FontAwesomeIconFactory; 20 | import javafx.beans.Observable; 21 | import javafx.beans.binding.Bindings; 22 | import javafx.geometry.Side; 23 | import javafx.scene.Node; 24 | import javafx.scene.control.ScrollPane; 25 | import javafx.scene.control.SkinBase; 26 | import javafx.scene.input.KeyCode; 27 | import javafx.scene.input.KeyEvent; 28 | import javafx.scene.layout.BorderPane; 29 | import javafx.scene.layout.StackPane; 30 | import javafx.scene.text.Text; 31 | import org.controlsfx.control.MasterDetailPane; 32 | 33 | import static com.calendarfx.view.RequestEvent.REQUEST_DATE; 34 | import static com.calendarfx.view.RequestEvent.REQUEST_DATE_TIME; 35 | import static com.calendarfx.view.RequestEvent.REQUEST_ENTRY; 36 | import static com.calendarfx.view.RequestEvent.REQUEST_WEEK; 37 | import static com.calendarfx.view.RequestEvent.REQUEST_YEAR; 38 | import static com.calendarfx.view.RequestEvent.REQUEST_YEAR_MONTH; 39 | import static com.calendarfx.view.YearMonthView.ClickBehaviour.PERFORM_SELECTION; 40 | import static javafx.geometry.Side.RIGHT; 41 | import static javafx.scene.control.SelectionMode.SINGLE; 42 | 43 | public class CalendarViewSkin extends SkinBase { 44 | 45 | private CustomMasterDetailPane leftMasterDetailPane; 46 | private SearchResultView searchResultView; 47 | private StackPane stackPane; 48 | 49 | public CalendarViewSkin(CalendarView view) { 50 | super(view); 51 | 52 | if (Boolean.getBoolean("calendarfx.developer")) { //$NON-NLS-1$ 53 | view.addEventFilter(KeyEvent.KEY_PRESSED, evt -> { 54 | if (evt.isMetaDown() && evt.getCode().equals(KeyCode.D)) { 55 | view.setShowDeveloperConsole( 56 | !view.isShowDeveloperConsole()); 57 | } 58 | }); 59 | } 60 | 61 | view.addEventHandler(REQUEST_DATE, evt -> view.showDate(evt.getDate())); 62 | view.addEventHandler(REQUEST_DATE_TIME, evt -> view.showDateTime(evt.getDateTime())); 63 | view.addEventHandler(REQUEST_WEEK, evt -> view.showWeek(evt.getYear(), evt.getWeekOfYear())); 64 | view.addEventHandler(REQUEST_YEAR_MONTH, evt -> view.showYearMonth(evt.getYearMonth())); 65 | view.addEventHandler(REQUEST_YEAR, evt -> view.showYear(evt.getYear())); 66 | view.addEventHandler(REQUEST_ENTRY, evt -> view.getSelectedPage().editEntry(evt.getEntry())); 67 | 68 | DayPage dayPage = view.getDayPage(); 69 | 70 | this.leftMasterDetailPane = new CustomMasterDetailPane(Side.LEFT); 71 | this.leftMasterDetailPane.setAnimated(false); 72 | this.leftMasterDetailPane.setShowDetailNode(true); 73 | 74 | TrayPane trayPane = new TrayPane(); 75 | 76 | // if (view.isShowSourceTray()) { 77 | // openTray(); 78 | // } else { 79 | // closeTray(); 80 | // } 81 | 82 | view.showSourceTrayProperty().addListener(it -> { 83 | if (view.isShowSourceTray()) { 84 | openTray(); 85 | } else { 86 | closeTray(); 87 | } 88 | }); 89 | 90 | // toolbar right 91 | 92 | Text searchIcon = FontAwesomeIconFactory.get().createIcon(FontAwesomeIcon.SEARCH); 93 | searchIcon.setId("search-icon"); //$NON-NLS-1$ 94 | 95 | BorderPane borderPane1 = new BorderPane(); 96 | 97 | borderPane1.topProperty().bind(view.headerProperty()); 98 | borderPane1.setCenter(stackPane = new StackPane()); 99 | borderPane1.bottomProperty().bind(view.footerProperty()); 100 | 101 | view.selectedPageProperty().addListener(it -> changePage()); 102 | 103 | leftMasterDetailPane.setMasterNode(borderPane1); 104 | leftMasterDetailPane.setDetailNode(trayPane); 105 | leftMasterDetailPane.setId("tray-pane"); //$NON-NLS-1$ 106 | leftMasterDetailPane.animatedProperty().bindBidirectional(view.traysAnimatedProperty()); 107 | leftMasterDetailPane.getStylesheets().add(CalendarFXControl.class.getResource("calendar.css").toExternalForm()); //$NON-NLS-1$ 108 | leftMasterDetailPane.setDividerPosition(.3); 109 | 110 | MasterDetailPane rightMasterDetailPane = new MasterDetailPane(RIGHT); 111 | searchResultView = view.getSearchResultView(); 112 | 113 | Bindings.bindContentBidirectional(searchResultView.getCalendarSources(), view.getCalendarSources()); 114 | 115 | searchResultView.zoneIdProperty().bind(view.zoneIdProperty()); 116 | searchResultView.selectedEntryProperty().addListener(evt -> showSelectedSearchResult()); 117 | 118 | view.showSearchResultsTrayProperty().bind(Bindings.not(Bindings.isEmpty(searchResultView.getSearchResults()))); 119 | 120 | rightMasterDetailPane.setDetailNode(searchResultView); 121 | rightMasterDetailPane.setMasterNode(leftMasterDetailPane); 122 | rightMasterDetailPane.showDetailNodeProperty().bind(view.showSearchResultsTrayProperty()); 123 | 124 | BorderPane borderPane = new BorderPane(); 125 | 126 | borderPane.setCenter(rightMasterDetailPane); 127 | 128 | if (Boolean.getBoolean("calendarfx.developer")) { //$NON-NLS-1$ 129 | DeveloperConsole developerConsole = view.getDeveloperConsole(); 130 | MasterDetailPane developerConsoleMasterDetailPane = new MasterDetailPane(Side.BOTTOM); 131 | developerConsoleMasterDetailPane.setDividerPosition(.6); 132 | developerConsoleMasterDetailPane.animatedProperty().bind(view.traysAnimatedProperty()); 133 | developerConsoleMasterDetailPane.getStyleClass().add("developer-master-detail-pane"); //$NON-NLS-1$ 134 | developerConsoleMasterDetailPane.setDetailSide(Side.BOTTOM); 135 | developerConsoleMasterDetailPane.setMasterNode(borderPane); 136 | developerConsoleMasterDetailPane.setDetailNode(developerConsole); 137 | developerConsoleMasterDetailPane.setShowDetailNode(true); 138 | developerConsoleMasterDetailPane.showDetailNodeProperty().bind(view.showDeveloperConsoleProperty()); 139 | developerConsoleMasterDetailPane.getStylesheets().add(CalendarFXControl.class.getResource("calendar.css").toExternalForm()); 140 | getChildren().add(developerConsoleMasterDetailPane); 141 | } else { 142 | getChildren().add(borderPane); 143 | } 144 | 145 | stackPane.getChildren().setAll(dayPage); 146 | } 147 | 148 | private void openTray() { 149 | leftMasterDetailPane.resetDividerPosition(); 150 | leftMasterDetailPane.setShowDetailNode(true); 151 | } 152 | 153 | private void closeTray() { 154 | leftMasterDetailPane.setShowDetailNode(false); 155 | } 156 | 157 | private void changePage() { 158 | CalendarView view = getSkinnable(); 159 | 160 | PageBase selectedPage = view.getSelectedPage(); 161 | 162 | selectedPage.setManaged(true); 163 | selectedPage.setVisible(true); 164 | 165 | /* 166 | * These values might have been changed if transitions were used 167 | * before. 168 | */ 169 | selectedPage.setScaleX(1); 170 | selectedPage.setScaleY(1); 171 | selectedPage.setOpacity(1); 172 | 173 | stackPane.getChildren().setAll(selectedPage); 174 | } 175 | 176 | private void showSelectedSearchResult() { 177 | Entry result = searchResultView.getSelectedEntry(); 178 | if (result != null) { 179 | getSkinnable().showEntry(result); 180 | } 181 | } 182 | 183 | class TrayPane extends BorderPane { 184 | private SourceView sourceView; 185 | private YearMonthView yearMonthView; 186 | 187 | public TrayPane() { 188 | // source view 189 | sourceView = getSkinnable().getSourceView(); 190 | sourceView.bind(getSkinnable()); 191 | 192 | // year month view 193 | yearMonthView = getSkinnable().getYearMonthView(); 194 | yearMonthView.setShowToday(false); 195 | yearMonthView.setShowTodayButton(false); 196 | yearMonthView.setId("date-picker"); //$NON-NLS-1$ 197 | yearMonthView.setSelectionMode(SINGLE); 198 | yearMonthView.setClickBehaviour(PERFORM_SELECTION); 199 | yearMonthView.getSelectedDates().add(getSkinnable().getDate()); 200 | yearMonthView.getSelectedDates().addListener((Observable evt) -> { 201 | if (yearMonthView.getSelectedDates().size() > 0) { 202 | yearMonthView.setDate(yearMonthView.getSelectedDates().iterator().next()); 203 | } 204 | }); 205 | 206 | getSkinnable().dateProperty().addListener(it -> { 207 | yearMonthView.getSelectedDates().clear(); 208 | yearMonthView.getSelectedDates().add(getSkinnable().getDate()); 209 | }); 210 | 211 | Bindings.bindBidirectional(yearMonthView.todayProperty(), getSkinnable().todayProperty()); 212 | Bindings.bindBidirectional(yearMonthView.dateProperty(), getSkinnable().dateProperty()); 213 | yearMonthView.weekFieldsProperty().bind(getSkinnable().weekFieldsProperty()); 214 | 215 | ScrollPane scrollPane = new ScrollPane(sourceView); 216 | 217 | scrollPane.getStyleClass().add("source-view-scroll-pane"); //$NON-NLS-1$ 218 | setCenter(scrollPane); 219 | setBottom(yearMonthView); 220 | } 221 | } 222 | 223 | private PrintView printView; 224 | 225 | private void print() { 226 | if (printView == null) { 227 | printView = getSkinnable().getPrintView(); 228 | } 229 | printView.setToday(getSkinnable().getToday()); 230 | printView.setWeekFields(getSkinnable().getWeekFields()); 231 | printView.getCalendarSources().setAll(getSkinnable().getCalendarSources()); 232 | printView.setLayout(getSkinnable().getSelectedPage().getLayout()); 233 | printView.setViewType(getSkinnable().getSelectedPage().getPrintViewType()); 234 | //printView.requestStartDate(getSkinnable().getDate()); 235 | printView.show(getSkinnable().getScene().getWindow()); 236 | } 237 | 238 | private class CustomMasterDetailPane extends MasterDetailPane { 239 | 240 | public CustomMasterDetailPane(Side side) { 241 | super(side); 242 | } 243 | 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/main/java/com/dlsc/jpro/calendar/CalendarView.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015, 2016 Dirk Lemmermann Software & Consulting (dlsc.com) 3 | *

4 | * This file is part of CalendarFX. 5 | */ 6 | 7 | package com.dlsc.jpro.calendar; 8 | 9 | import com.calendarfx.view.DateControl; 10 | import com.calendarfx.view.DeveloperConsole; 11 | import com.calendarfx.view.SearchResultView; 12 | import com.calendarfx.view.SourceView; 13 | import com.calendarfx.view.YearMonthView; 14 | import com.calendarfx.view.page.DayPage; 15 | import com.calendarfx.view.page.DayPage.DayPageLayout; 16 | import com.calendarfx.view.page.MonthPage; 17 | import com.calendarfx.view.page.PageBase; 18 | import com.calendarfx.view.page.WeekPage; 19 | import com.calendarfx.view.page.YearPage; 20 | import com.calendarfx.view.print.PrintView; 21 | import javafx.beans.InvalidationListener; 22 | import javafx.beans.property.BooleanProperty; 23 | import javafx.beans.property.ObjectProperty; 24 | import javafx.beans.property.ReadOnlyObjectProperty; 25 | import javafx.beans.property.ReadOnlyObjectWrapper; 26 | import javafx.beans.property.SimpleBooleanProperty; 27 | import javafx.beans.property.SimpleObjectProperty; 28 | import javafx.beans.value.ObservableValue; 29 | import javafx.collections.MapChangeListener.Change; 30 | import javafx.collections.ObservableList; 31 | import javafx.scene.Node; 32 | import javafx.scene.control.Skin; 33 | import javafx.scene.layout.BorderPane; 34 | import org.controlsfx.control.PropertySheet.Item; 35 | 36 | import java.time.LocalDate; 37 | import java.time.LocalDateTime; 38 | import java.time.Year; 39 | import java.time.YearMonth; 40 | import java.util.Optional; 41 | 42 | import static java.util.Objects.requireNonNull; 43 | 44 | /** 45 | * A full uk.co.senapt.desktop.ui.modules.calendar view with multiple pages for displaying a single day, a week, 46 | * a month, and an entire year. The view also includes two trays, one for seeing 47 | * all uk.co.senapt.desktop.ui.modules.calendar sources, and one for seeing the results of the current search. 48 | * The trays can be shown or hidden. Another nice feature is direct support for 49 | * printing (see {@link #getPrintView()}). 50 | *

51 | *

52 | */ 53 | public class CalendarView extends DateControl { 54 | 55 | private static final String DEFAULT_STYLE_CLASS = "calendar-view"; 56 | 57 | private static final String SELECTED_PAGE = "com.calendarfx.selectedPage"; //$NON-NLS-1$ 58 | 59 | private SourceView sourceView; 60 | 61 | private SearchResultView searchResultView; 62 | 63 | private YearMonthView yearMonthView; 64 | 65 | private DayPage dayPage; 66 | 67 | private WeekPage weekPage; 68 | 69 | private MonthPage monthPage; 70 | 71 | private YearPage yearPage; 72 | 73 | private DeveloperConsole developerConsole; 74 | 75 | private PrintView printView; 76 | 77 | private final InvalidationListener fixSelectedPageListener = it -> fixSelectedPage(); 78 | 79 | /** 80 | * Constructs a new uk.co.senapt.desktop.ui.modules.calendar view. 81 | */ 82 | public CalendarView() { 83 | getStyleClass().add(DEFAULT_STYLE_CLASS); 84 | 85 | this.dayPage = new DayPage(); 86 | 87 | bind(dayPage, true); 88 | 89 | this.sourceView = new SourceView(); 90 | this.searchResultView = new SearchResultView(); 91 | this.yearMonthView = new YearMonthView(); 92 | 93 | if (Boolean.getBoolean("calendarfx.developer")) { //$NON-NLS-1$ 94 | this.developerConsole = new DeveloperConsole(); 95 | this.developerConsole.setDateControl(this); 96 | } 97 | 98 | selectedPage.set(dayPage); 99 | 100 | /* 101 | * We do have a user agent stylesheet, but it doesn't seem to work 102 | * properly when run as a standalone jar file. 103 | */ 104 | getStylesheets().add(com.calendarfx.view.CalendarView.class.getResource("calendar.css").toExternalForm()); //$NON-NLS-1$ 105 | 106 | /* 107 | * We are "abusing" the properties map to pass new values of read-only 108 | * properties from the skin to the control. 109 | */ 110 | getProperties().addListener((Change change) -> { 111 | if (change.getKey().equals(SELECTED_PAGE)) { 112 | if (change.getValueAdded() != null) { 113 | PageBase page = (PageBase) change.getValueAdded(); 114 | selectedPage.set(page); 115 | getProperties().remove(SELECTED_PAGE); 116 | } 117 | } 118 | }); 119 | 120 | dayPage.hiddenProperty().addListener(fixSelectedPageListener); 121 | dayPage.setDayPageLayout(DayPageLayout.DAY_ONLY); 122 | fixSelectedPage(); 123 | 124 | setTraysAnimated(false); 125 | 126 | getYearMonthView().setShowWeekNumbers(false); 127 | } 128 | 129 | private void fixSelectedPage() { 130 | PageBase page = getSelectedPage(); 131 | if (page == null || page.isHidden()) { 132 | if (page == dayPage) { 133 | selectedPage.set(weekPage); 134 | } else if (page == weekPage) { 135 | selectedPage.set(monthPage); 136 | } else if (page == monthPage) { 137 | selectedPage.set(yearPage); 138 | } else if (page == yearPage) { 139 | selectedPage.set(dayPage); 140 | } 141 | } 142 | } 143 | 144 | @Override 145 | protected Skin createDefaultSkin() { 146 | return new CalendarViewSkin(this); 147 | } 148 | 149 | /** 150 | * Returns the developer console that can be made visible via a META-D key 151 | * stroke when the system property "calendarfx.developer" is set to true. 152 | * 153 | * @return the developer console or null if the system property 154 | * "calendarfx.developer" is not set to true 155 | */ 156 | public final DeveloperConsole getDeveloperConsole() { 157 | return developerConsole; 158 | } 159 | 160 | /** 161 | * Returns the day page. 162 | * 163 | * @return the day page 164 | */ 165 | public final DayPage getDayPage() { 166 | return dayPage; 167 | } 168 | 169 | /** 170 | * Returns the week page. 171 | * 172 | * @return the week page 173 | */ 174 | public final WeekPage getWeekPage() { 175 | if (weekPage == null) { 176 | weekPage = new WeekPage(); 177 | weekPage.hiddenProperty().addListener(fixSelectedPageListener); 178 | bind(weekPage, true); 179 | } 180 | return weekPage; 181 | } 182 | 183 | /** 184 | * Returns the month page. 185 | * 186 | * @return the month page 187 | */ 188 | public final MonthPage getMonthPage() { 189 | if (monthPage == null) { 190 | monthPage = new MonthPage(); 191 | monthPage.hiddenProperty().addListener(fixSelectedPageListener); 192 | bind(monthPage, true); 193 | } 194 | return monthPage; 195 | } 196 | 197 | /** 198 | * Returns the year page. 199 | * 200 | * @return the year page 201 | */ 202 | public final YearPage getYearPage() { 203 | if (yearPage == null) { 204 | yearPage = new YearPage(); 205 | yearPage.hiddenProperty().addListener(fixSelectedPageListener); 206 | bind(yearPage, true); 207 | } 208 | return yearPage; 209 | } 210 | 211 | /** 212 | * Returns the search result view child control. 213 | * 214 | * @return the search result view 215 | */ 216 | public final SearchResultView getSearchResultView() { 217 | return searchResultView; 218 | } 219 | 220 | /** 221 | * Returns the source view child control. 222 | * 223 | * @return the source view 224 | */ 225 | public final SourceView getSourceView() { 226 | return sourceView; 227 | } 228 | 229 | /** 230 | * Returns the year month view child control. 231 | * 232 | * @return the year month view 233 | */ 234 | public final YearMonthView getYearMonthView() { 235 | return yearMonthView; 236 | } 237 | 238 | /** 239 | * Returns the print view associated with this view. The print view shows a print 240 | * result preview dialog that allows the user to customize several printing options 241 | * and trigger a print job to be executed. 242 | * 243 | * @return the print view 244 | */ 245 | public final PrintView getPrintView() { 246 | if (printView == null) { 247 | printView = new PrintView(); 248 | } 249 | 250 | return printView; 251 | } 252 | 253 | private final BooleanProperty showDevoloperConsole = new SimpleBooleanProperty(this, "showDevoloperConsole", false); //$NON-NLS-1$ 254 | 255 | /** 256 | * Controls the visibility of the developer console. The console displays 257 | * various types of events that are fired by the uk.co.senapt.desktop.ui.modules.calendar while the user is 258 | * using it. 259 | * 260 | * @return true if the developer console will be shown to the user 261 | */ 262 | public final BooleanProperty showDeveloperConsoleProperty() { 263 | return showDevoloperConsole; 264 | } 265 | 266 | /** 267 | * Sets the value of {@link #showDeveloperConsoleProperty()}. 268 | * 269 | * @param show if true will show the developer console 270 | */ 271 | public final void setShowDeveloperConsole(boolean show) { 272 | showDeveloperConsoleProperty().set(show); 273 | } 274 | 275 | /** 276 | * Returns the value of {@link #showSourceTrayProperty()}. 277 | * 278 | * @return true if the developer console gets shown to the user 279 | */ 280 | public final boolean isShowDeveloperConsole() { 281 | return showDeveloperConsoleProperty().get(); 282 | } 283 | 284 | private final BooleanProperty showSourceTray = new SimpleBooleanProperty(this, "showSourceTray", false); //$NON-NLS-1$ 285 | 286 | /** 287 | * Controls the visibility of the source tray. 288 | * 289 | * @return true if the source tray will be shown to the user 290 | */ 291 | public final BooleanProperty showSourceTrayProperty() { 292 | return showSourceTray; 293 | } 294 | 295 | /** 296 | * Sets the value of {@link #showSourceTrayProperty()}. 297 | * 298 | * @param show if true will show the tray 299 | */ 300 | public final void setShowSourceTray(boolean show) { 301 | showSourceTray.set(show); 302 | } 303 | 304 | /** 305 | * Returns the value of {@link #showSourceTrayProperty()}. 306 | * 307 | * @return true if the uk.co.senapt.desktop.ui.modules.calendar source tray gets shown to the user 308 | */ 309 | public final boolean isShowSourceTray() { 310 | return showSourceTray.get(); 311 | } 312 | 313 | private final BooleanProperty showSearchResultsTray = new SimpleBooleanProperty(this, "showSearchResultsTray", false); //$NON-NLS-1$ 314 | 315 | /** 316 | * Controls the visibility of the search results tray. 317 | * 318 | * @return the search result tray visibility 319 | */ 320 | public final BooleanProperty showSearchResultsTrayProperty() { 321 | return showSearchResultsTray; 322 | } 323 | 324 | /** 325 | * Sets the value of {@link #showSearchResultsTrayProperty()}. 326 | * 327 | * @param show if true the search result tray will be shown to the user 328 | */ 329 | public final void setShowSearchResultsTray(boolean show) { 330 | showSearchResultsTray.set(show); 331 | } 332 | 333 | /** 334 | * Returns the value of {@link #showSearchResultsTrayProperty()}. 335 | * 336 | * @return true if the search result tray is visible 337 | */ 338 | public final boolean isShowSearchResultsTray() { 339 | return showSearchResultsTray.get(); 340 | } 341 | 342 | private final ReadOnlyObjectWrapper selectedPage = new ReadOnlyObjectWrapper<>(this, "selectedPage"); 343 | 344 | /** 345 | * A read-only property used for storing the currently selected page. 346 | * 347 | * @return the selected page view 348 | */ 349 | public final ReadOnlyObjectProperty selectedPageProperty() { 350 | return selectedPage.getReadOnlyProperty(); 351 | } 352 | 353 | /** 354 | * The value of {@link #selectedPageProperty()}. 355 | * 356 | * @return the selected page view 357 | */ 358 | public final PageBase getSelectedPage() { 359 | return selectedPageProperty().get(); 360 | } 361 | 362 | private final ObjectProperty header = new SimpleObjectProperty<>(this, "header", null); //$NON-NLS-1$ 363 | 364 | /** 365 | * Property used to reference a node that can be used as a header for the 366 | * uk.co.senapt.desktop.ui.modules.calendar view. The skin of this view uses a {@link BorderPane} to lay out 367 | * its children. The header will be placed in its top location. 368 | * 369 | * @return a node added as a header to the view (e.g. a tool bar) 370 | */ 371 | public final ObjectProperty headerProperty() { 372 | return header; 373 | } 374 | 375 | /** 376 | * Returns the value of {@link #headerProperty()}. 377 | * 378 | * @return the node that will be shown above the actual uk.co.senapt.desktop.ui.modules.calendar 379 | */ 380 | public final Node getHeader() { 381 | return headerProperty().get(); 382 | } 383 | 384 | /** 385 | * Sets the value of {@link #headerProperty()}. 386 | * 387 | * @param node a node that will be shown above the actual uk.co.senapt.desktop.ui.modules.calendar 388 | */ 389 | public final void setHeader(Node node) { 390 | headerProperty().set(node); 391 | } 392 | 393 | private final ObjectProperty footer = new SimpleObjectProperty<>(this, "footer", null); //$NON-NLS-1$ 394 | 395 | /** 396 | * Property used to reference a node that can be used as a footer for the 397 | * uk.co.senapt.desktop.ui.modules.calendar view. The skin of this view uses a {@link BorderPane} to lay out 398 | * its children. The footer will be placed in its bottom location. 399 | * 400 | * @return a node added as a footer to the view (e.g. a status bar) 401 | */ 402 | public final ObjectProperty footerProperty() { 403 | return footer; 404 | } 405 | 406 | /** 407 | * Returns the value of {@link #footerProperty()}. 408 | * 409 | * @return the header node shown below the actual uk.co.senapt.desktop.ui.modules.calendar 410 | */ 411 | public final Node getFooter() { 412 | return footerProperty().get(); 413 | } 414 | 415 | /** 416 | * Sets the value of {@link #footerProperty()}. 417 | * 418 | * @param node a node that will be shown below the actual uk.co.senapt.desktop.ui.modules.calendar 419 | */ 420 | public final void setFooter(Node node) { 421 | footerProperty().set(node); 422 | } 423 | 424 | private final BooleanProperty transitionsEnabled = new SimpleBooleanProperty(this, "transitionsEnabled", true); //$NON-NLS-1$ 425 | 426 | /** 427 | * A property used to control whether switching from one page to another 428 | * will be done with a graphics transition. 429 | * 430 | * @return true if transitions (eye candy) are enabled 431 | */ 432 | public final BooleanProperty transitionsEnabledProperty() { 433 | return this.transitionsEnabled; 434 | } 435 | 436 | /** 437 | * Returns the value of {@link #transitionsEnabledProperty()}. 438 | * 439 | * @return true if transitions are enabled 440 | */ 441 | public final boolean isTransitionsEnabled() { 442 | return transitionsEnabledProperty().get(); 443 | } 444 | 445 | /** 446 | * Sets the value of {@link #transitionsEnabledProperty()}. 447 | * 448 | * @param transitions if true transitions will be used to go from one page to 449 | * another 450 | */ 451 | public final void setTransitionsEnabled(boolean transitions) { 452 | transitionsEnabledProperty().set(transitions); 453 | } 454 | 455 | // tray animation support 456 | 457 | private final BooleanProperty traysAnimated = new SimpleBooleanProperty(this, "traysAnimated", true); //$NON-NLS-1$ 458 | 459 | /** 460 | * A property used to control whether closing or opening the trays (source view, 461 | * search result view) will be animated. 462 | * 463 | * @return true if animations (eye candy) are enabled 464 | */ 465 | public final BooleanProperty traysAnimatedProperty() { 466 | return this.traysAnimated; 467 | } 468 | 469 | /** 470 | * Returns the value of {@link #traysAnimatedProperty()}. 471 | * 472 | * @return true if tray animations are enabled 473 | */ 474 | public final boolean isTraysAnimated() { 475 | return traysAnimatedProperty().get(); 476 | } 477 | 478 | /** 479 | * Sets the value of {@link #traysAnimatedProperty()}. 480 | * 481 | * @param animated if true tray animations will be used when opening / closing 482 | * the source tray or the search result tray 483 | */ 484 | public final void setTraysAnimated(boolean animated) { 485 | traysAnimatedProperty().set(animated); 486 | } 487 | 488 | // show search field support 489 | 490 | private final BooleanProperty showSearchField = new SimpleBooleanProperty(this, "showSearchField", true); 491 | 492 | /** 493 | * Controls whether the search field (text field) in the upper right corner 494 | * of the control will be shown to the user or not. 495 | * 496 | * @return true if the search field will be accessible by the user 497 | */ 498 | public final BooleanProperty showSearchFieldProperty() { 499 | return showSearchField; 500 | } 501 | 502 | /** 503 | * Returns the value of {@link #showSearchFieldProperty()}. 504 | * 505 | * @return true if the search field will be accessible by the user 506 | */ 507 | public final boolean isShowSearchField() { 508 | return showSearchField.get(); 509 | } 510 | 511 | /** 512 | * Sets the value of {@link #showSearchFieldProperty()}. 513 | * 514 | * @param show if true the search field will be accessible by the user 515 | */ 516 | public final void setShowSearchField(boolean show) { 517 | showSearchField.set(show); 518 | } 519 | 520 | private final BooleanProperty showSourceTrayButton = new SimpleBooleanProperty(this, "showSourceTrayButton", true); 521 | 522 | /** 523 | * Controls whether the source tray button in the upper left corner of the 524 | * control will be shown to the user or not. 525 | * 526 | * @return true if the source tray button will be accessible by the user 527 | */ 528 | public final BooleanProperty showSourceTrayButtonProperty() { 529 | return showSourceTrayButton; 530 | } 531 | 532 | /** 533 | * Returns the value of {@link #showSourceTrayButtonProperty()}. 534 | * 535 | * @return true if the source tray button will be accessible by the user 536 | */ 537 | public final boolean isShowSourceTrayButton() { 538 | return showSourceTrayButton.get(); 539 | } 540 | 541 | /** 542 | * Sets the value of {@link #showSourceTrayButtonProperty()}. 543 | * 544 | * @param show if true the source tray button will be accessible by the user 545 | */ 546 | public final void setShowSourceTrayButton(boolean show) { 547 | showSourceTrayButton.set(show); 548 | } 549 | 550 | private final BooleanProperty showAddCalendarButton = new SimpleBooleanProperty(this, "showAddCalendarButton", true); 551 | 552 | /** 553 | * Controls whether the "add uk.co.senapt.desktop.ui.modules.calendar" button in the upper left corner of 554 | * the control will be shown to the user or not. 555 | * 556 | * @return true if the "add uk.co.senapt.desktop.ui.modules.calendar" button will be accessible by the user 557 | */ 558 | public final BooleanProperty showAddCalendarButtonProperty() { 559 | return showAddCalendarButton; 560 | } 561 | 562 | /** 563 | * Returns the value of {@link #showAddCalendarButtonProperty()}. 564 | * 565 | * @return true if the "add uk.co.senapt.desktop.ui.modules.calendar" button will be accessible by the user 566 | */ 567 | public final boolean isShowAddCalendarButton() { 568 | return showAddCalendarButton.get(); 569 | } 570 | 571 | /** 572 | * Sets the value of {@link #showAddCalendarButtonProperty()}. 573 | * 574 | * @param show if true the "add uk.co.senapt.desktop.ui.modules.calendar" button will be accessible by the 575 | * user 576 | */ 577 | public final void setShowAddCalendarButton(boolean show) { 578 | showAddCalendarButton.set(show); 579 | } 580 | 581 | private final BooleanProperty showPrintButton = new SimpleBooleanProperty(this, "showPrintButton", true); 582 | 583 | /** 584 | * Controls whether the "print" button in the upper left corner of the 585 | * control will be shown to the user or not. 586 | * 587 | * @return true if the "print" button will be accessible by the user 588 | */ 589 | public final BooleanProperty showPrintButtonProperty() { 590 | return showPrintButton; 591 | } 592 | 593 | /** 594 | * Returns the value of {@link #showPrintButtonProperty()}. 595 | * 596 | * @return true if the "print" button will be accessible by the user 597 | */ 598 | public final boolean isShowPrintButton() { 599 | return showPrintButton.get(); 600 | } 601 | 602 | /** 603 | * Sets the value of {@link #showPrintButtonProperty()}. 604 | * 605 | * @param show if true the "print" button will be accessible by the user 606 | */ 607 | public final void setShowPrintButton(boolean show) { 608 | showPrintButton.set(show); 609 | } 610 | 611 | private final BooleanProperty showPageToolBarControls = new SimpleBooleanProperty(this, "showPageToolBarControls", true); 612 | 613 | /** 614 | * Controls whether the "page-specific" toolbar controls (e.g. DayPage: 615 | * agenda view, day view, combined view) in the upper left corner of the 616 | * control will be shown to the user or not. 617 | * 618 | * @return true if the "page-specific" toolbar controls will be accessible 619 | * by the user 620 | * @see PageBase#getToolBarControls() 621 | */ 622 | public final BooleanProperty showPageToolBarControlsProperty() { 623 | return showPageToolBarControls; 624 | } 625 | 626 | /** 627 | * Returns the value of {@link #showPageToolBarControlsProperty()}. 628 | * 629 | * @return true if the "page-specific" toolbar controls will be accessible 630 | * by the user 631 | * @see PageBase#getToolBarControls() 632 | */ 633 | public final boolean isShowPageToolBarControls() { 634 | return showPageToolBarControls.get(); 635 | } 636 | 637 | /** 638 | * Sets the value of {@link #showPageToolBarControlsProperty()}. 639 | * 640 | * @param show if true the "page-specific" toolbar controls will be 641 | * accessible by the user 642 | * @see PageBase#getToolBarControls() 643 | */ 644 | public final void setShowPageToolBarControls(boolean show) { 645 | showPageToolBarControls.set(show); 646 | } 647 | 648 | private final BooleanProperty showPageSwitcher = new SimpleBooleanProperty(this, "showPageSwitcher", true); 649 | 650 | /** 651 | * Controls whether the page switcher (day, week, month, year) will be shown 652 | * to the user or not. 653 | * 654 | * @return true if the toolbar will be shown to the user 655 | */ 656 | public final BooleanProperty showPageSwitcherProperty() { 657 | return showPageSwitcher; 658 | } 659 | 660 | /** 661 | * Returns the value of {@link #showPageSwitcherProperty()}. 662 | * 663 | * @return true if the page switcher will be visible 664 | */ 665 | public final boolean isShowPageSwitcher() { 666 | return showPageSwitcher.get(); 667 | } 668 | 669 | /** 670 | * Sets the value of {@link #showPageSwitcherProperty()}. 671 | * 672 | * @param show true if the page switcher will be visible 673 | */ 674 | public final void setShowPageSwitcher(boolean show) { 675 | showPageSwitcher.set(show); 676 | } 677 | 678 | /** 679 | * Switches the view to the {@link DayPage}. 680 | */ 681 | public final void showDayPage() { 682 | selectedPage.set(getDayPage()); 683 | } 684 | 685 | /** 686 | * Switches the view to the {@link WeekPage}. 687 | */ 688 | public final void showWeekPage() { 689 | selectedPage.set(getWeekPage()); 690 | } 691 | 692 | /** 693 | * Switches the view to the {@link MonthPage}. 694 | */ 695 | public final void showMonthPage() { 696 | selectedPage.set(getMonthPage()); 697 | } 698 | 699 | /** 700 | * Switches the view to the {@link YearPage}. 701 | */ 702 | public final void showYearPage() { 703 | selectedPage.set(getYearPage()); 704 | } 705 | 706 | /** 707 | * Sends the request to the uk.co.senapt.desktop.ui.modules.calendar view to display the given date. The 708 | * view will switch to the {@link DayPage} and set the value of 709 | * {@link #dateProperty()} to the date. 710 | * 711 | * @param date the date to show in the view 712 | */ 713 | public final void showDate(LocalDate date) { 714 | requireNonNull(date); 715 | if (!dayPage.isHidden()) { 716 | selectedPage.set(getDayPage()); 717 | } else if (!weekPage.isHidden()) { 718 | selectedPage.set(getWeekPage()); 719 | } else if (!monthPage.isHidden()) { 720 | selectedPage.set(getMonthPage()); 721 | } else if (!yearPage.isHidden()) { 722 | selectedPage.set(getYearPage()); 723 | } 724 | 725 | setDate(date); 726 | } 727 | 728 | /** 729 | * Sends the request to the uk.co.senapt.desktop.ui.modules.calendar view to display the given week. The 730 | * view will try to switch to the {@link WeekPage} and set the value of 731 | * {@link #dateProperty()} to the date. 732 | * 733 | * @param year the date to show in the view 734 | * @param weekOfYear the week to show in the view 735 | */ 736 | public final void showWeek(Year year, int weekOfYear) { 737 | requireNonNull(year); 738 | if (weekOfYear < 1) { 739 | throw new IllegalArgumentException("illegal value for week of year: " + weekOfYear); 740 | } 741 | if (!weekPage.isHidden()) { 742 | selectedPage.set(getWeekPage()); 743 | } else if (!monthPage.isHidden()) { 744 | selectedPage.set(getMonthPage()); 745 | } else if (!yearPage.isHidden()) { 746 | selectedPage.set(getYearPage()); 747 | } 748 | 749 | setDate(LocalDate.of(year.getValue(), 1, 1).plusWeeks(weekOfYear)); 750 | } 751 | 752 | /** 753 | * Sends the request to the uk.co.senapt.desktop.ui.modules.calendar view to display the given date and 754 | * time. The view will switch to the {@link DayPage} and set the value of 755 | * {@link #dateProperty()} to the date and {@link #requestedTimeProperty()} 756 | * to the time. 757 | * 758 | * @param dateTime the date and time to show in the view 759 | */ 760 | public final void showDateTime(LocalDateTime dateTime) { 761 | requireNonNull(dateTime); 762 | 763 | if (!dayPage.isHidden()) { 764 | selectedPage.set(getDayPage()); 765 | } else if (!weekPage.isHidden()) { 766 | selectedPage.set(getWeekPage()); 767 | } else if (!monthPage.isHidden()) { 768 | selectedPage.set(getMonthPage()); 769 | } else if (!yearPage.isHidden()) { 770 | selectedPage.set(getYearPage()); 771 | } 772 | 773 | setDate(dateTime.toLocalDate()); 774 | setRequestedTime(dateTime.toLocalTime()); 775 | } 776 | 777 | /** 778 | * Sends the request to the uk.co.senapt.desktop.ui.modules.calendar view to display the given year and 779 | * month. The view will switch to the {@link MonthPage} and set the value of 780 | * {@link #dateProperty()} to the first day of the month. 781 | * 782 | * @param yearMonth the year and month to show in the view 783 | */ 784 | public final void showYearMonth(YearMonth yearMonth) { 785 | requireNonNull(yearMonth); 786 | 787 | if (!monthPage.isHidden()) { 788 | selectedPage.set(getMonthPage()); 789 | } else if (!yearPage.isHidden()) { 790 | selectedPage.set(getYearPage()); 791 | } 792 | 793 | setDate(yearMonth.atDay(1)); 794 | } 795 | 796 | /** 797 | * Sends the request to the uk.co.senapt.desktop.ui.modules.calendar view to display the given year. The 798 | * view will switch to the {@link YearPage} and set the value of 799 | * {@link #dateProperty()} to the first day of the year. 800 | * 801 | * @param year the year to show in the view 802 | */ 803 | public final void showYear(Year year) { 804 | requireNonNull(year); 805 | if (!yearPage.isHidden()) { 806 | selectedPage.set(getYearPage()); 807 | setDate(year.atDay(1)); 808 | } 809 | } 810 | 811 | private final String CALENDAR_VIEW_CATEGORY = "Calendar View"; //$NON-NLS-1$ 812 | 813 | @Override 814 | public ObservableList getPropertySheetItems() { 815 | ObservableList items = super.getPropertySheetItems(); 816 | 817 | items.add(new Item() { 818 | 819 | @Override 820 | public Optional> getObservableValue() { 821 | return Optional.of(showSourceTrayProperty()); 822 | } 823 | 824 | @Override 825 | public void setValue(Object value) { 826 | setShowSourceTray((boolean) value); 827 | } 828 | 829 | @Override 830 | public Object getValue() { 831 | return isShowSourceTray(); 832 | } 833 | 834 | @Override 835 | public Class getType() { 836 | return Boolean.class; 837 | } 838 | 839 | @Override 840 | public String getName() { 841 | return "Calendar Tray"; //$NON-NLS-1$ 842 | } 843 | 844 | @Override 845 | public String getDescription() { 846 | return "Show or hide the uk.co.senapt.desktop.ui.modules.calendar tray on the left"; //$NON-NLS-1$ 847 | } 848 | 849 | @Override 850 | public String getCategory() { 851 | return CALENDAR_VIEW_CATEGORY; 852 | } 853 | }); 854 | 855 | items.add(new Item() { 856 | 857 | @Override 858 | public Optional> getObservableValue() { 859 | return Optional.of(showSearchResultsTrayProperty()); 860 | } 861 | 862 | @Override 863 | public void setValue(Object value) { 864 | setShowSearchResultsTray((boolean) value); 865 | } 866 | 867 | @Override 868 | public Object getValue() { 869 | return isShowSearchResultsTray(); 870 | } 871 | 872 | @Override 873 | public Class getType() { 874 | return Boolean.class; 875 | } 876 | 877 | @Override 878 | public String getName() { 879 | return "Search Results Tray"; //$NON-NLS-1$ 880 | } 881 | 882 | @Override 883 | public String getDescription() { 884 | return "Show or hide the search results tray on the right"; //$NON-NLS-1$ 885 | } 886 | 887 | @Override 888 | public String getCategory() { 889 | return CALENDAR_VIEW_CATEGORY; 890 | } 891 | }); 892 | 893 | items.add(new Item() { 894 | 895 | @Override 896 | public Optional> getObservableValue() { 897 | return Optional.of(transitionsEnabledProperty()); 898 | } 899 | 900 | @Override 901 | public void setValue(Object value) { 902 | setTransitionsEnabled((boolean) value); 903 | } 904 | 905 | @Override 906 | public Object getValue() { 907 | return isTransitionsEnabled(); 908 | } 909 | 910 | @Override 911 | public Class getType() { 912 | return Boolean.class; 913 | } 914 | 915 | @Override 916 | public String getName() { 917 | return "Transitions"; //$NON-NLS-1$ 918 | } 919 | 920 | @Override 921 | public String getDescription() { 922 | return "Use transitions when changing pages."; //$NON-NLS-1$ 923 | } 924 | 925 | @Override 926 | public String getCategory() { 927 | return CALENDAR_VIEW_CATEGORY; 928 | } 929 | }); 930 | 931 | items.add(new Item() { 932 | 933 | @Override 934 | public Optional> getObservableValue() { 935 | return Optional.of(showSearchFieldProperty()); 936 | } 937 | 938 | @Override 939 | public void setValue(Object value) { 940 | setShowSearchField((boolean) value); 941 | } 942 | 943 | @Override 944 | public Object getValue() { 945 | return isShowSearchField(); 946 | } 947 | 948 | @Override 949 | public Class getType() { 950 | return Boolean.class; 951 | } 952 | 953 | @Override 954 | public String getName() { 955 | return "Show Search Field"; //$NON-NLS-1$ 956 | } 957 | 958 | @Override 959 | public String getDescription() { 960 | return "Can the user access the search field or not."; //$NON-NLS-1$ 961 | } 962 | 963 | @Override 964 | public String getCategory() { 965 | return CALENDAR_VIEW_CATEGORY; 966 | } 967 | }); 968 | 969 | items.add(new Item() { 970 | 971 | @Override 972 | public Optional> getObservableValue() { 973 | return Optional.of(showSourceTrayButtonProperty()); 974 | } 975 | 976 | @Override 977 | public void setValue(Object value) { 978 | setShowSourceTrayButton((boolean) value); 979 | } 980 | 981 | @Override 982 | public Object getValue() { 983 | return isShowSourceTrayButton(); 984 | } 985 | 986 | @Override 987 | public Class getType() { 988 | return Boolean.class; 989 | } 990 | 991 | @Override 992 | public String getName() { 993 | return "Source Tray Button"; //$NON-NLS-1$ 994 | } 995 | 996 | @Override 997 | public String getDescription() { 998 | return "Can the user access the source tray button or not."; //$NON-NLS-1$ 999 | } 1000 | 1001 | @Override 1002 | public String getCategory() { 1003 | return CALENDAR_VIEW_CATEGORY; 1004 | } 1005 | }); 1006 | 1007 | items.add(new Item() { 1008 | 1009 | @Override 1010 | public Optional> getObservableValue() { 1011 | return Optional.of(showAddCalendarButtonProperty()); 1012 | } 1013 | 1014 | @Override 1015 | public void setValue(Object value) { 1016 | setShowAddCalendarButton((boolean) value); 1017 | } 1018 | 1019 | @Override 1020 | public Object getValue() { 1021 | return isShowAddCalendarButton(); 1022 | } 1023 | 1024 | @Override 1025 | public Class getType() { 1026 | return Boolean.class; 1027 | } 1028 | 1029 | @Override 1030 | public String getName() { 1031 | return "Add Calendar Button"; //$NON-NLS-1$ 1032 | } 1033 | 1034 | @Override 1035 | public String getDescription() { 1036 | return "Can the user access the button to add new calendars or not."; //$NON-NLS-1$ 1037 | } 1038 | 1039 | @Override 1040 | public String getCategory() { 1041 | return CALENDAR_VIEW_CATEGORY; 1042 | } 1043 | }); 1044 | 1045 | items.add(new Item() { 1046 | 1047 | @Override 1048 | public Optional> getObservableValue() { 1049 | return Optional.of(showPrintButtonProperty()); 1050 | } 1051 | 1052 | @Override 1053 | public void setValue(Object value) { 1054 | setShowPrintButton((boolean) value); 1055 | } 1056 | 1057 | @Override 1058 | public Object getValue() { 1059 | return isShowPrintButton(); 1060 | } 1061 | 1062 | @Override 1063 | public Class getType() { 1064 | return Boolean.class; 1065 | } 1066 | 1067 | @Override 1068 | public String getName() { 1069 | return "Print Button"; //$NON-NLS-1$ 1070 | } 1071 | 1072 | @Override 1073 | public String getDescription() { 1074 | return "Can the user access the button to print calendars or not."; //$NON-NLS-1$ 1075 | } 1076 | 1077 | @Override 1078 | public String getCategory() { 1079 | return CALENDAR_VIEW_CATEGORY; 1080 | } 1081 | }); 1082 | 1083 | items.add(new Item() { 1084 | 1085 | @Override 1086 | public Optional> getObservableValue() { 1087 | return Optional.of(showPageToolBarControlsProperty()); 1088 | } 1089 | 1090 | @Override 1091 | public void setValue(Object value) { 1092 | setShowPageToolBarControls((boolean) value); 1093 | } 1094 | 1095 | @Override 1096 | public Object getValue() { 1097 | return isShowPageToolBarControls(); 1098 | } 1099 | 1100 | @Override 1101 | public Class getType() { 1102 | return Boolean.class; 1103 | } 1104 | 1105 | @Override 1106 | public String getName() { 1107 | return "Page Controls"; //$NON-NLS-1$ 1108 | } 1109 | 1110 | @Override 1111 | public String getDescription() { 1112 | return "Can the user access the page-specific toolbar controls or not."; //$NON-NLS-1$ 1113 | } 1114 | 1115 | @Override 1116 | public String getCategory() { 1117 | return CALENDAR_VIEW_CATEGORY; 1118 | } 1119 | }); 1120 | 1121 | items.add(new Item() { 1122 | 1123 | @Override 1124 | public Optional> getObservableValue() { 1125 | return Optional.of(showPageSwitcherProperty()); 1126 | } 1127 | 1128 | @Override 1129 | public void setValue(Object value) { 1130 | setShowPageSwitcher((boolean) value); 1131 | } 1132 | 1133 | @Override 1134 | public Object getValue() { 1135 | return isShowPageSwitcher(); 1136 | } 1137 | 1138 | @Override 1139 | public Class getType() { 1140 | return Boolean.class; 1141 | } 1142 | 1143 | @Override 1144 | public String getName() { 1145 | return "Show Page Switcher"; //$NON-NLS-1$ 1146 | } 1147 | 1148 | @Override 1149 | public String getDescription() { 1150 | return "Visibility of the switcher."; //$NON-NLS-1$ 1151 | } 1152 | 1153 | @Override 1154 | public String getCategory() { 1155 | return CALENDAR_VIEW_CATEGORY; 1156 | } 1157 | }); 1158 | 1159 | return items; 1160 | } 1161 | } 1162 | --------------------------------------------------------------------------------