├── AddressApp-Part-4
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ └── org.eclipse.jdt.core.prefs
├── resources
│ ├── images
│ │ ├── edit.png
│ │ ├── calendar.png
│ │ └── address_book_32.png
│ └── copyright.txt
├── .gitignore
├── build.fxbuild
├── .classpath
├── .project
└── src
│ └── ch
│ └── makery
│ └── address
│ ├── view
│ ├── RootLayout.fxml
│ ├── PersonEditDialog.fxml
│ ├── DarkTheme.css
│ ├── PersonOverview.fxml
│ ├── PersonEditDialogController.java
│ └── PersonOverviewController.java
│ ├── util
│ └── DateUtil.java
│ ├── model
│ └── Person.java
│ └── MainApp.java
├── AddressApp-Part-5
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ └── org.eclipse.jdt.core.prefs
├── resources
│ ├── images
│ │ ├── edit.png
│ │ ├── calendar.png
│ │ └── address_book_32.png
│ └── copyright.txt
├── .gitignore
├── build.fxbuild
├── .classpath
├── .project
└── src
│ └── ch
│ └── makery
│ └── address
│ ├── util
│ ├── LocalDateAdapter.java
│ └── DateUtil.java
│ ├── model
│ ├── PersonListWrapper.java
│ └── Person.java
│ └── view
│ ├── RootLayout.fxml
│ ├── PersonEditDialog.fxml
│ ├── RootLayoutController.java
│ ├── DarkTheme.css
│ ├── PersonOverview.fxml
│ └── PersonEditDialogController.java
├── AddressApp-Part-6
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ └── org.eclipse.jdt.core.prefs
├── resources
│ ├── images
│ │ ├── edit.png
│ │ ├── calendar.png
│ │ └── address_book_32.png
│ └── copyright.txt
├── .gitignore
├── build.fxbuild
├── .classpath
├── .project
└── src
│ └── ch
│ └── makery
│ └── address
│ ├── util
│ ├── LocalDateAdapter.java
│ └── DateUtil.java
│ ├── model
│ ├── PersonListWrapper.java
│ └── Person.java
│ └── view
│ ├── BirthdayStatistics.fxml
│ ├── BirthdayStatisticsController.java
│ ├── RootLayout.fxml
│ ├── PersonEditDialog.fxml
│ ├── DarkTheme.css
│ ├── RootLayoutController.java
│ ├── PersonOverview.fxml
│ └── PersonEditDialogController.java
├── AddressApp-Part-7
├── .settings
│ ├── org.eclipse.core.resources.prefs
│ └── org.eclipse.jdt.core.prefs
├── resources
│ ├── images
│ │ ├── edit.png
│ │ ├── calendar.png
│ │ └── address_book_32.png
│ └── copyright.txt
├── build
│ ├── dist
│ │ └── resources
│ │ │ ├── images
│ │ │ ├── edit.png
│ │ │ ├── calendar.png
│ │ │ └── address_book_32.png
│ │ │ └── copyright.txt
│ ├── package
│ │ ├── macosx
│ │ │ ├── AddressApp.icns
│ │ │ └── AddressApp-volume.icns
│ │ └── windows
│ │ │ ├── AddressApp.ico
│ │ │ └── AddressApp-setup-icon.bmp
│ └── build.xml
├── .gitignore
├── .classpath
├── build.fxbuild
├── .project
└── src
│ └── ch
│ └── makery
│ └── address
│ ├── util
│ ├── LocalDateAdapter.java
│ └── DateUtil.java
│ ├── model
│ ├── PersonListWrapper.java
│ └── Person.java
│ └── view
│ ├── BirthdayStatistics.fxml
│ ├── BirthdayStatisticsController.java
│ ├── RootLayout.fxml
│ ├── PersonEditDialog.fxml
│ ├── DarkTheme.css
│ ├── RootLayoutController.java
│ ├── PersonOverview.fxml
│ └── PersonEditDialogController.java
├── README.md
├── .gitignore
├── AddressApp-Part-1
├── .gitignore
├── build.fxbuild
├── .classpath
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── .project
└── src
│ └── ch
│ └── makery
│ └── address
│ ├── view
│ ├── RootLayout.fxml
│ └── PersonOverview.fxml
│ └── MainApp.java
├── AddressApp-Part-2
├── .gitignore
├── build.fxbuild
├── .classpath
├── .settings
│ └── org.eclipse.jdt.core.prefs
├── .project
└── src
│ └── ch
│ └── makery
│ └── address
│ ├── view
│ ├── RootLayout.fxml
│ ├── PersonOverviewController.java
│ └── PersonOverview.fxml
│ ├── model
│ └── Person.java
│ └── MainApp.java
└── AddressApp-Part-3
├── .gitignore
├── build.fxbuild
├── .classpath
├── .settings
└── org.eclipse.jdt.core.prefs
├── .project
└── src
└── ch
└── makery
└── address
├── view
├── RootLayout.fxml
├── PersonEditDialog.fxml
├── PersonOverview.fxml
├── PersonEditDialogController.java
└── PersonOverviewController.java
├── util
└── DateUtil.java
├── model
└── Person.java
└── MainApp.java
/AddressApp-Part-4/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//resources/copyright.txt=UTF-8
3 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//resources/copyright.txt=UTF-8
3 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//resources/copyright.txt=UTF-8
3 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding//resources/copyright.txt=UTF-8
3 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/resources/images/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-4/resources/images/edit.png
--------------------------------------------------------------------------------
/AddressApp-Part-5/resources/images/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-5/resources/images/edit.png
--------------------------------------------------------------------------------
/AddressApp-Part-6/resources/images/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-6/resources/images/edit.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/resources/images/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/resources/images/edit.png
--------------------------------------------------------------------------------
/AddressApp-Part-4/resources/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-4/resources/images/calendar.png
--------------------------------------------------------------------------------
/AddressApp-Part-5/resources/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-5/resources/images/calendar.png
--------------------------------------------------------------------------------
/AddressApp-Part-6/resources/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-6/resources/images/calendar.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/resources/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/resources/images/calendar.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaFX 8 Tutorial - Sources
2 |
3 | These are example sources for the [JavaFX 8 Tutorial](http://code.makery.ch/java/javafx-8-tutorial-intro/).
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-4/resources/images/address_book_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-4/resources/images/address_book_32.png
--------------------------------------------------------------------------------
/AddressApp-Part-5/resources/images/address_book_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-5/resources/images/address_book_32.png
--------------------------------------------------------------------------------
/AddressApp-Part-6/resources/images/address_book_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-6/resources/images/address_book_32.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/dist/resources/images/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/dist/resources/images/edit.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/package/macosx/AddressApp.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/package/macosx/AddressApp.icns
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/package/windows/AddressApp.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/package/windows/AddressApp.ico
--------------------------------------------------------------------------------
/AddressApp-Part-7/resources/images/address_book_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/resources/images/address_book_32.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/dist/resources/images/calendar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/dist/resources/images/calendar.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/package/macosx/AddressApp-volume.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/package/macosx/AddressApp-volume.icns
--------------------------------------------------------------------------------
/AddressApp-Part-1/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-2/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-3/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-4/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-5/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-6/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-7/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 | /bin
5 | /.metadata
6 | /target*
7 |
8 | # Locally stored "Eclipse launch configurations"
9 | /*.launch
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/dist/resources/images/address_book_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/dist/resources/images/address_book_32.png
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/package/windows/AddressApp-setup-icon.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marcojakob/tutorial-javafx-8/HEAD/AddressApp-Part-7/build/package/windows/AddressApp-setup-icon.bmp
--------------------------------------------------------------------------------
/AddressApp-Part-4/resources/copyright.txt:
--------------------------------------------------------------------------------
1 | Copyright by Susumu Yoshida - http://www.mcdodesign.com/
2 | - address_book_32.png
3 | - AddressApp.ico
4 |
5 | Copyright by Jan Jan Kovařík - http://glyphicons.com/
6 | - calendar.png
7 | - edit.png
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/resources/copyright.txt:
--------------------------------------------------------------------------------
1 | Copyright by Susumu Yoshida - http://www.mcdodesign.com/
2 | - address_book_32.png
3 | - AddressApp.ico
4 |
5 | Copyright by Jan Jan Kovařík - http://glyphicons.com/
6 | - calendar.png
7 | - edit.png
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/resources/copyright.txt:
--------------------------------------------------------------------------------
1 | Copyright by Susumu Yoshida - http://www.mcdodesign.com/
2 | - address_book_32.png
3 | - AddressApp.ico
4 |
5 | Copyright by Jan Jan Kovařík - http://glyphicons.com/
6 | - calendar.png
7 | - edit.png
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/resources/copyright.txt:
--------------------------------------------------------------------------------
1 | Copyright by Susumu Yoshida - http://www.mcdodesign.com/
2 | - address_book_32.png
3 | - AddressApp.ico
4 |
5 | Copyright by Jan Jan Kovařík - http://glyphicons.com/
6 | - calendar.png
7 | - edit.png
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/dist/resources/copyright.txt:
--------------------------------------------------------------------------------
1 | Copyright by Susumu Yoshida - http://www.mcdodesign.com/
2 | - address_book_32.png
3 | - AddressApp.ico
4 |
5 | Copyright by Jan Jan Kovařík - http://glyphicons.com/
6 | - calendar.png
7 | - edit.png
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-1/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-1/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/build.fxbuild:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/AddressApp-Part-1/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
5 | org.eclipse.jdt.core.compiler.compliance=1.8
6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate
7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate
8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate
9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
11 | org.eclipse.jdt.core.compiler.source=1.8
12 |
--------------------------------------------------------------------------------
/AddressApp-Part-1/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-1
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-2
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-3
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-4
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-5
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-6
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | AddressApp-Part-7
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.xtext.ui.shared.xtextBuilder
15 |
16 |
17 |
18 |
19 |
20 | org.eclipse.xtext.ui.shared.xtextNature
21 | org.eclipse.jdt.core.javanature
22 |
23 |
24 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/util/LocalDateAdapter.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javax.xml.bind.annotation.adapters.XmlAdapter;
6 |
7 | /**
8 | * Adapter (for JAXB) to convert between the LocalDate and the ISO 8601
9 | * String representation of the date such as '2012-12-03'.
10 | *
11 | * @author Marco Jakob
12 | */
13 | public class LocalDateAdapter extends XmlAdapter {
14 |
15 | @Override
16 | public LocalDate unmarshal(String v) throws Exception {
17 | return LocalDate.parse(v);
18 | }
19 |
20 | @Override
21 | public String marshal(LocalDate v) throws Exception {
22 | return v.toString();
23 | }
24 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/util/LocalDateAdapter.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javax.xml.bind.annotation.adapters.XmlAdapter;
6 |
7 | /**
8 | * Adapter (for JAXB) to convert between the LocalDate and the ISO 8601
9 | * String representation of the date such as '2012-12-03'.
10 | *
11 | * @author Marco Jakob
12 | */
13 | public class LocalDateAdapter extends XmlAdapter {
14 |
15 | @Override
16 | public LocalDate unmarshal(String v) throws Exception {
17 | return LocalDate.parse(v);
18 | }
19 |
20 | @Override
21 | public String marshal(LocalDate v) throws Exception {
22 | return v.toString();
23 | }
24 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/util/LocalDateAdapter.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javax.xml.bind.annotation.adapters.XmlAdapter;
6 |
7 | /**
8 | * Adapter (for JAXB) to convert between the LocalDate and the ISO 8601
9 | * String representation of the date such as '2012-12-03'.
10 | *
11 | * @author Marco Jakob
12 | */
13 | public class LocalDateAdapter extends XmlAdapter {
14 |
15 | @Override
16 | public LocalDate unmarshal(String v) throws Exception {
17 | return LocalDate.parse(v);
18 | }
19 |
20 | @Override
21 | public String marshal(LocalDate v) throws Exception {
22 | return v.toString();
23 | }
24 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/model/PersonListWrapper.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.util.List;
4 |
5 | import javax.xml.bind.annotation.XmlElement;
6 | import javax.xml.bind.annotation.XmlRootElement;
7 |
8 | /**
9 | * Helper class to wrap a list of persons. This is used for saving the
10 | * list of persons to XML.
11 | *
12 | * @author Marco Jakob
13 | */
14 | @XmlRootElement(name = "persons")
15 | public class PersonListWrapper {
16 |
17 | private List persons;
18 |
19 | @XmlElement(name = "person")
20 | public List getPersons() {
21 | return persons;
22 | }
23 |
24 | public void setPersons(List persons) {
25 | this.persons = persons;
26 | }
27 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/model/PersonListWrapper.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.util.List;
4 |
5 | import javax.xml.bind.annotation.XmlElement;
6 | import javax.xml.bind.annotation.XmlRootElement;
7 |
8 | /**
9 | * Helper class to wrap a list of persons. This is used for saving the
10 | * list of persons to XML.
11 | *
12 | * @author Marco Jakob
13 | */
14 | @XmlRootElement(name = "persons")
15 | public class PersonListWrapper {
16 |
17 | private List persons;
18 |
19 | @XmlElement(name = "person")
20 | public List getPersons() {
21 | return persons;
22 | }
23 |
24 | public void setPersons(List persons) {
25 | this.persons = persons;
26 | }
27 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/model/PersonListWrapper.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.util.List;
4 |
5 | import javax.xml.bind.annotation.XmlElement;
6 | import javax.xml.bind.annotation.XmlRootElement;
7 |
8 | /**
9 | * Helper class to wrap a list of persons. This is used for saving the
10 | * list of persons to XML.
11 | *
12 | * @author Marco Jakob
13 | */
14 | @XmlRootElement(name = "persons")
15 | public class PersonListWrapper {
16 |
17 | private List persons;
18 |
19 | @XmlElement(name = "person")
20 | public List getPersons() {
21 | return persons;
22 | }
23 |
24 | public void setPersons(List persons) {
25 | this.persons = persons;
26 | }
27 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/BirthdayStatistics.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/BirthdayStatistics.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/AddressApp-Part-1/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
23 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
23 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
23 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
22 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/src/ch/makery/address/view/PersonOverviewController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Label;
5 | import javafx.scene.control.TableColumn;
6 | import javafx.scene.control.TableView;
7 | import ch.makery.address.MainApp;
8 | import ch.makery.address.model.Person;
9 |
10 | public class PersonOverviewController {
11 | @FXML
12 | private TableView personTable;
13 | @FXML
14 | private TableColumn firstNameColumn;
15 | @FXML
16 | private TableColumn lastNameColumn;
17 |
18 | @FXML
19 | private Label firstNameLabel;
20 | @FXML
21 | private Label lastNameLabel;
22 | @FXML
23 | private Label streetLabel;
24 | @FXML
25 | private Label postalCodeLabel;
26 | @FXML
27 | private Label cityLabel;
28 | @FXML
29 | private Label birthdayLabel;
30 |
31 | // Reference to the main application.
32 | private MainApp mainApp;
33 |
34 | /**
35 | * The constructor.
36 | * The constructor is called before the initialize() method.
37 | */
38 | public PersonOverviewController() {
39 | }
40 |
41 | /**
42 | * Initializes the controller class. This method is automatically called
43 | * after the fxml file has been loaded.
44 | */
45 | @FXML
46 | private void initialize() {
47 | // Initialize the person table with the two columns.
48 | firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
49 | lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
50 | }
51 |
52 | /**
53 | * Is called by the main application to give a reference back to itself.
54 | *
55 | * @param mainApp
56 | */
57 | public void setMainApp(MainApp mainApp) {
58 | this.mainApp = mainApp;
59 |
60 | // Add observable list data to the table
61 | personTable.setItems(mainApp.getPersonData());
62 | }
63 | }
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/util/DateUtil.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 | import java.time.format.DateTimeFormatter;
5 | import java.time.format.DateTimeParseException;
6 |
7 | /**
8 | * Helper functions for handling dates.
9 | *
10 | * @author Marco Jakob
11 | */
12 | public class DateUtil {
13 |
14 | /** The date pattern that is used for conversion. Change as you wish. */
15 | private static final String DATE_PATTERN = "dd.MM.yyyy";
16 |
17 | /** The date formatter. */
18 | private static final DateTimeFormatter DATE_FORMATTER =
19 | DateTimeFormatter.ofPattern(DATE_PATTERN);
20 |
21 | /**
22 | * Returns the given date as a well formatted String. The above defined
23 | * {@link DateUtil#DATE_PATTERN} is used.
24 | *
25 | * @param date the date to be returned as a string
26 | * @return formatted string
27 | */
28 | public static String format(LocalDate date) {
29 | if (date == null) {
30 | return null;
31 | }
32 | return DATE_FORMATTER.format(date);
33 | }
34 |
35 | /**
36 | * Converts a String in the format of the defined {@link DateUtil#DATE_PATTERN}
37 | * to a {@link LocalDate} object.
38 | *
39 | * Returns null if the String could not be converted.
40 | *
41 | * @param dateString the date as String
42 | * @return the date object or null if it could not be converted
43 | */
44 | public static LocalDate parse(String dateString) {
45 | try {
46 | return DATE_FORMATTER.parse(dateString, LocalDate::from);
47 | } catch (DateTimeParseException e) {
48 | return null;
49 | }
50 | }
51 |
52 | /**
53 | * Checks the String whether it is a valid date.
54 | *
55 | * @param dateString
56 | * @return true if the String is a valid date
57 | */
58 | public static boolean validDate(String dateString) {
59 | // Try to parse the String.
60 | return DateUtil.parse(dateString) != null;
61 | }
62 | }
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/util/DateUtil.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 | import java.time.format.DateTimeFormatter;
5 | import java.time.format.DateTimeParseException;
6 |
7 | /**
8 | * Helper functions for handling dates.
9 | *
10 | * @author Marco Jakob
11 | */
12 | public class DateUtil {
13 |
14 | /** The date pattern that is used for conversion. Change as you wish. */
15 | private static final String DATE_PATTERN = "dd.MM.yyyy";
16 |
17 | /** The date formatter. */
18 | private static final DateTimeFormatter DATE_FORMATTER =
19 | DateTimeFormatter.ofPattern(DATE_PATTERN);
20 |
21 | /**
22 | * Returns the given date as a well formatted String. The above defined
23 | * {@link DateUtil#DATE_PATTERN} is used.
24 | *
25 | * @param date the date to be returned as a string
26 | * @return formatted string
27 | */
28 | public static String format(LocalDate date) {
29 | if (date == null) {
30 | return null;
31 | }
32 | return DATE_FORMATTER.format(date);
33 | }
34 |
35 | /**
36 | * Converts a String in the format of the defined {@link DateUtil#DATE_PATTERN}
37 | * to a {@link LocalDate} object.
38 | *
39 | * Returns null if the String could not be converted.
40 | *
41 | * @param dateString the date as String
42 | * @return the date object or null if it could not be converted
43 | */
44 | public static LocalDate parse(String dateString) {
45 | try {
46 | return DATE_FORMATTER.parse(dateString, LocalDate::from);
47 | } catch (DateTimeParseException e) {
48 | return null;
49 | }
50 | }
51 |
52 | /**
53 | * Checks the String whether it is a valid date.
54 | *
55 | * @param dateString
56 | * @return true if the String is a valid date
57 | */
58 | public static boolean validDate(String dateString) {
59 | // Try to parse the String.
60 | return DateUtil.parse(dateString) != null;
61 | }
62 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/util/DateUtil.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 | import java.time.format.DateTimeFormatter;
5 | import java.time.format.DateTimeParseException;
6 |
7 | /**
8 | * Helper functions for handling dates.
9 | *
10 | * @author Marco Jakob
11 | */
12 | public class DateUtil {
13 |
14 | /** The date pattern that is used for conversion. Change as you wish. */
15 | private static final String DATE_PATTERN = "dd.MM.yyyy";
16 |
17 | /** The date formatter. */
18 | private static final DateTimeFormatter DATE_FORMATTER =
19 | DateTimeFormatter.ofPattern(DATE_PATTERN);
20 |
21 | /**
22 | * Returns the given date as a well formatted String. The above defined
23 | * {@link DateUtil#DATE_PATTERN} is used.
24 | *
25 | * @param date the date to be returned as a string
26 | * @return formatted string
27 | */
28 | public static String format(LocalDate date) {
29 | if (date == null) {
30 | return null;
31 | }
32 | return DATE_FORMATTER.format(date);
33 | }
34 |
35 | /**
36 | * Converts a String in the format of the defined {@link DateUtil#DATE_PATTERN}
37 | * to a {@link LocalDate} object.
38 | *
39 | * Returns null if the String could not be converted.
40 | *
41 | * @param dateString the date as String
42 | * @return the date object or null if it could not be converted
43 | */
44 | public static LocalDate parse(String dateString) {
45 | try {
46 | return DATE_FORMATTER.parse(dateString, LocalDate::from);
47 | } catch (DateTimeParseException e) {
48 | return null;
49 | }
50 | }
51 |
52 | /**
53 | * Checks the String whether it is a valid date.
54 | *
55 | * @param dateString
56 | * @return true if the String is a valid date
57 | */
58 | public static boolean validDate(String dateString) {
59 | // Try to parse the String.
60 | return DateUtil.parse(dateString) != null;
61 | }
62 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/util/DateUtil.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 | import java.time.format.DateTimeFormatter;
5 | import java.time.format.DateTimeParseException;
6 |
7 | /**
8 | * Helper functions for handling dates.
9 | *
10 | * @author Marco Jakob
11 | */
12 | public class DateUtil {
13 |
14 | /** The date pattern that is used for conversion. Change as you wish. */
15 | private static final String DATE_PATTERN = "dd.MM.yyyy";
16 |
17 | /** The date formatter. */
18 | private static final DateTimeFormatter DATE_FORMATTER =
19 | DateTimeFormatter.ofPattern(DATE_PATTERN);
20 |
21 | /**
22 | * Returns the given date as a well formatted String. The above defined
23 | * {@link DateUtil#DATE_PATTERN} is used.
24 | *
25 | * @param date the date to be returned as a string
26 | * @return formatted string
27 | */
28 | public static String format(LocalDate date) {
29 | if (date == null) {
30 | return null;
31 | }
32 | return DATE_FORMATTER.format(date);
33 | }
34 |
35 | /**
36 | * Converts a String in the format of the defined {@link DateUtil#DATE_PATTERN}
37 | * to a {@link LocalDate} object.
38 | *
39 | * Returns null if the String could not be converted.
40 | *
41 | * @param dateString the date as String
42 | * @return the date object or null if it could not be converted
43 | */
44 | public static LocalDate parse(String dateString) {
45 | try {
46 | return DATE_FORMATTER.parse(dateString, LocalDate::from);
47 | } catch (DateTimeParseException e) {
48 | return null;
49 | }
50 | }
51 |
52 | /**
53 | * Checks the String whether it is a valid date.
54 | *
55 | * @param dateString
56 | * @return true if the String is a valid date
57 | */
58 | public static boolean validDate(String dateString) {
59 | // Try to parse the String.
60 | return DateUtil.parse(dateString) != null;
61 | }
62 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/util/DateUtil.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.util;
2 |
3 | import java.time.LocalDate;
4 | import java.time.format.DateTimeFormatter;
5 | import java.time.format.DateTimeParseException;
6 |
7 | /**
8 | * Helper functions for handling dates.
9 | *
10 | * @author Marco Jakob
11 | */
12 | public class DateUtil {
13 |
14 | /** The date pattern that is used for conversion. Change as you wish. */
15 | private static final String DATE_PATTERN = "dd.MM.yyyy";
16 |
17 | /** The date formatter. */
18 | private static final DateTimeFormatter DATE_FORMATTER =
19 | DateTimeFormatter.ofPattern(DATE_PATTERN);
20 |
21 | /**
22 | * Returns the given date as a well formatted String. The above defined
23 | * {@link DateUtil#DATE_PATTERN} is used.
24 | *
25 | * @param date the date to be returned as a string
26 | * @return formatted string
27 | */
28 | public static String format(LocalDate date) {
29 | if (date == null) {
30 | return null;
31 | }
32 | return DATE_FORMATTER.format(date);
33 | }
34 |
35 | /**
36 | * Converts a String in the format of the defined {@link DateUtil#DATE_PATTERN}
37 | * to a {@link LocalDate} object.
38 | *
39 | * Returns null if the String could not be converted.
40 | *
41 | * @param dateString the date as String
42 | * @return the date object or null if it could not be converted
43 | */
44 | public static LocalDate parse(String dateString) {
45 | try {
46 | return DATE_FORMATTER.parse(dateString, LocalDate::from);
47 | } catch (DateTimeParseException e) {
48 | return null;
49 | }
50 | }
51 |
52 | /**
53 | * Checks the String whether it is a valid date.
54 | *
55 | * @param dateString
56 | * @return true if the String is a valid date
57 | */
58 | public static boolean validDate(String dateString) {
59 | // Try to parse the String.
60 | return DateUtil.parse(dateString) != null;
61 | }
62 | }
--------------------------------------------------------------------------------
/AddressApp-Part-1/src/ch/makery/address/MainApp.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address;
2 |
3 | import java.io.IOException;
4 |
5 | import javafx.application.Application;
6 | import javafx.fxml.FXMLLoader;
7 | import javafx.scene.Scene;
8 | import javafx.scene.layout.AnchorPane;
9 | import javafx.scene.layout.BorderPane;
10 | import javafx.stage.Stage;
11 |
12 | public class MainApp extends Application {
13 |
14 | private Stage primaryStage;
15 | private BorderPane rootLayout;
16 |
17 | @Override
18 | public void start(Stage primaryStage) {
19 | this.primaryStage = primaryStage;
20 | this.primaryStage.setTitle("AddressApp");
21 |
22 | initRootLayout();
23 |
24 | showPersonOverview();
25 | }
26 |
27 | /**
28 | * Initializes the root layout.
29 | */
30 | public void initRootLayout() {
31 | try {
32 | // Load root layout from fxml file.
33 | FXMLLoader loader = new FXMLLoader();
34 | loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
35 | rootLayout = (BorderPane) loader.load();
36 |
37 | // Show the scene containing the root layout.
38 | Scene scene = new Scene(rootLayout);
39 | primaryStage.setScene(scene);
40 | primaryStage.show();
41 | } catch (IOException e) {
42 | e.printStackTrace();
43 | }
44 | }
45 |
46 | /**
47 | * Shows the person overview inside the root layout.
48 | */
49 | public void showPersonOverview() {
50 | try {
51 | // Load person overview.
52 | FXMLLoader loader = new FXMLLoader();
53 | loader.setLocation(MainApp.class.getResource("view/PersonOverview.fxml"));
54 | AnchorPane personOverview = (AnchorPane) loader.load();
55 |
56 | // Set person overview into the center of root layout.
57 | rootLayout.setCenter(personOverview);
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | }
61 | }
62 |
63 | /**
64 | * Returns the main stage.
65 | * @return
66 | */
67 | public Stage getPrimaryStage() {
68 | return primaryStage;
69 | }
70 |
71 | public static void main(String[] args) {
72 | launch(args);
73 | }
74 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
34 |
39 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/BirthdayStatisticsController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import java.text.DateFormatSymbols;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.Locale;
7 |
8 | import javafx.collections.FXCollections;
9 | import javafx.collections.ObservableList;
10 | import javafx.fxml.FXML;
11 | import javafx.scene.chart.BarChart;
12 | import javafx.scene.chart.CategoryAxis;
13 | import javafx.scene.chart.XYChart;
14 | import ch.makery.address.model.Person;
15 |
16 | /**
17 | * The controller for the birthday statistics view.
18 | *
19 | * @author Marco Jakob
20 | */
21 | public class BirthdayStatisticsController {
22 |
23 | @FXML
24 | private BarChart barChart;
25 |
26 | @FXML
27 | private CategoryAxis xAxis;
28 |
29 | private ObservableList monthNames = FXCollections.observableArrayList();
30 |
31 | /**
32 | * Initializes the controller class. This method is automatically called
33 | * after the fxml file has been loaded.
34 | */
35 | @FXML
36 | private void initialize() {
37 | // Get an array with the English month names.
38 | String[] months = DateFormatSymbols.getInstance(Locale.ENGLISH).getMonths();
39 | // Convert it to a list and add it to our ObservableList of months.
40 | monthNames.addAll(Arrays.asList(months));
41 |
42 | // Assign the month names as categories for the horizontal axis.
43 | xAxis.setCategories(monthNames);
44 | }
45 |
46 | /**
47 | * Sets the persons to show the statistics for.
48 | *
49 | * @param persons
50 | */
51 | public void setPersonData(List persons) {
52 | // Count the number of people having their birthday in a specific month.
53 | int[] monthCounter = new int[12];
54 | for (Person p : persons) {
55 | int month = p.getBirthday().getMonthValue() - 1;
56 | monthCounter[month]++;
57 | }
58 |
59 | XYChart.Series series = new XYChart.Series<>();
60 |
61 | // Create a XYChart.Data object for each month. Add it to the series.
62 | for (int i = 0; i < monthCounter.length; i++) {
63 | series.getData().add(new XYChart.Data<>(monthNames.get(i), monthCounter[i]));
64 | }
65 |
66 | barChart.getData().add(series);
67 | }
68 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/BirthdayStatisticsController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import java.text.DateFormatSymbols;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.Locale;
7 |
8 | import javafx.collections.FXCollections;
9 | import javafx.collections.ObservableList;
10 | import javafx.fxml.FXML;
11 | import javafx.scene.chart.BarChart;
12 | import javafx.scene.chart.CategoryAxis;
13 | import javafx.scene.chart.XYChart;
14 | import ch.makery.address.model.Person;
15 |
16 | /**
17 | * The controller for the birthday statistics view.
18 | *
19 | * @author Marco Jakob
20 | */
21 | public class BirthdayStatisticsController {
22 |
23 | @FXML
24 | private BarChart barChart;
25 |
26 | @FXML
27 | private CategoryAxis xAxis;
28 |
29 | private ObservableList monthNames = FXCollections.observableArrayList();
30 |
31 | /**
32 | * Initializes the controller class. This method is automatically called
33 | * after the fxml file has been loaded.
34 | */
35 | @FXML
36 | private void initialize() {
37 | // Get an array with the English month names.
38 | String[] months = DateFormatSymbols.getInstance(Locale.ENGLISH).getMonths();
39 | // Convert it to a list and add it to our ObservableList of months.
40 | monthNames.addAll(Arrays.asList(months));
41 |
42 | // Assign the month names as categories for the horizontal axis.
43 | xAxis.setCategories(monthNames);
44 | }
45 |
46 | /**
47 | * Sets the persons to show the statistics for.
48 | *
49 | * @param persons
50 | */
51 | public void setPersonData(List persons) {
52 | // Count the number of people having their birthday in a specific month.
53 | int[] monthCounter = new int[12];
54 | for (Person p : persons) {
55 | int month = p.getBirthday().getMonthValue() - 1;
56 | monthCounter[month]++;
57 | }
58 |
59 | XYChart.Series series = new XYChart.Series<>();
60 |
61 | // Create a XYChart.Data object for each month. Add it to the series.
62 | for (int i = 0; i < monthCounter.length; i++) {
63 | series.getData().add(new XYChart.Data<>(monthNames.get(i), monthCounter[i]));
64 | }
65 |
66 | barChart.getData().add(series);
67 | }
68 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
34 |
39 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/RootLayout.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
34 |
39 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/view/PersonEditDialog.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/view/PersonEditDialog.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/view/PersonEditDialog.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/PersonEditDialog.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/PersonEditDialog.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/src/ch/makery/address/model/Person.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleObjectProperty;
9 | import javafx.beans.property.SimpleStringProperty;
10 | import javafx.beans.property.StringProperty;
11 |
12 | /**
13 | * Model class for a Person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class Person {
18 |
19 | private final StringProperty firstName;
20 | private final StringProperty lastName;
21 | private final StringProperty street;
22 | private final IntegerProperty postalCode;
23 | private final StringProperty city;
24 | private final ObjectProperty birthday;
25 |
26 | /**
27 | * Default constructor.
28 | */
29 | public Person() {
30 | this(null, null);
31 | }
32 |
33 | /**
34 | * Constructor with some initial data.
35 | *
36 | * @param firstName
37 | * @param lastName
38 | */
39 | public Person(String firstName, String lastName) {
40 | this.firstName = new SimpleStringProperty(firstName);
41 | this.lastName = new SimpleStringProperty(lastName);
42 |
43 | // Some initial dummy data, just for convenient testing.
44 | this.street = new SimpleStringProperty("some street");
45 | this.postalCode = new SimpleIntegerProperty(1234);
46 | this.city = new SimpleStringProperty("some city");
47 | this.birthday = new SimpleObjectProperty(LocalDate.of(1999, 2, 21));
48 | }
49 |
50 | public String getFirstName() {
51 | return firstName.get();
52 | }
53 |
54 | public void setFirstName(String firstName) {
55 | this.firstName.set(firstName);
56 | }
57 |
58 | public StringProperty firstNameProperty() {
59 | return firstName;
60 | }
61 |
62 | public String getLastName() {
63 | return lastName.get();
64 | }
65 |
66 | public void setLastName(String lastName) {
67 | this.lastName.set(lastName);
68 | }
69 |
70 | public StringProperty lastNameProperty() {
71 | return lastName;
72 | }
73 |
74 | public String getStreet() {
75 | return street.get();
76 | }
77 |
78 | public void setStreet(String street) {
79 | this.street.set(street);
80 | }
81 |
82 | public StringProperty streetProperty() {
83 | return street;
84 | }
85 |
86 | public int getPostalCode() {
87 | return postalCode.get();
88 | }
89 |
90 | public void setPostalCode(int postalCode) {
91 | this.postalCode.set(postalCode);
92 | }
93 |
94 | public IntegerProperty postalCodeProperty() {
95 | return postalCode;
96 | }
97 |
98 | public String getCity() {
99 | return city.get();
100 | }
101 |
102 | public void setCity(String city) {
103 | this.city.set(city);
104 | }
105 |
106 | public StringProperty cityProperty() {
107 | return city;
108 | }
109 |
110 | public LocalDate getBirthday() {
111 | return birthday.get();
112 | }
113 |
114 | public void setBirthday(LocalDate birthday) {
115 | this.birthday.set(birthday);
116 | }
117 |
118 | public ObjectProperty birthdayProperty() {
119 | return birthday;
120 | }
121 | }
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/model/Person.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleObjectProperty;
9 | import javafx.beans.property.SimpleStringProperty;
10 | import javafx.beans.property.StringProperty;
11 |
12 | /**
13 | * Model class for a Person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class Person {
18 |
19 | private final StringProperty firstName;
20 | private final StringProperty lastName;
21 | private final StringProperty street;
22 | private final IntegerProperty postalCode;
23 | private final StringProperty city;
24 | private final ObjectProperty birthday;
25 |
26 | /**
27 | * Default constructor.
28 | */
29 | public Person() {
30 | this(null, null);
31 | }
32 |
33 | /**
34 | * Constructor with some initial data.
35 | *
36 | * @param firstName
37 | * @param lastName
38 | */
39 | public Person(String firstName, String lastName) {
40 | this.firstName = new SimpleStringProperty(firstName);
41 | this.lastName = new SimpleStringProperty(lastName);
42 |
43 | // Some initial dummy data, just for convenient testing.
44 | this.street = new SimpleStringProperty("some street");
45 | this.postalCode = new SimpleIntegerProperty(1234);
46 | this.city = new SimpleStringProperty("some city");
47 | this.birthday = new SimpleObjectProperty(LocalDate.of(1999, 2, 21));
48 | }
49 |
50 | public String getFirstName() {
51 | return firstName.get();
52 | }
53 |
54 | public void setFirstName(String firstName) {
55 | this.firstName.set(firstName);
56 | }
57 |
58 | public StringProperty firstNameProperty() {
59 | return firstName;
60 | }
61 |
62 | public String getLastName() {
63 | return lastName.get();
64 | }
65 |
66 | public void setLastName(String lastName) {
67 | this.lastName.set(lastName);
68 | }
69 |
70 | public StringProperty lastNameProperty() {
71 | return lastName;
72 | }
73 |
74 | public String getStreet() {
75 | return street.get();
76 | }
77 |
78 | public void setStreet(String street) {
79 | this.street.set(street);
80 | }
81 |
82 | public StringProperty streetProperty() {
83 | return street;
84 | }
85 |
86 | public int getPostalCode() {
87 | return postalCode.get();
88 | }
89 |
90 | public void setPostalCode(int postalCode) {
91 | this.postalCode.set(postalCode);
92 | }
93 |
94 | public IntegerProperty postalCodeProperty() {
95 | return postalCode;
96 | }
97 |
98 | public String getCity() {
99 | return city.get();
100 | }
101 |
102 | public void setCity(String city) {
103 | this.city.set(city);
104 | }
105 |
106 | public StringProperty cityProperty() {
107 | return city;
108 | }
109 |
110 | public LocalDate getBirthday() {
111 | return birthday.get();
112 | }
113 |
114 | public void setBirthday(LocalDate birthday) {
115 | this.birthday.set(birthday);
116 | }
117 |
118 | public ObjectProperty birthdayProperty() {
119 | return birthday;
120 | }
121 | }
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/model/Person.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleObjectProperty;
9 | import javafx.beans.property.SimpleStringProperty;
10 | import javafx.beans.property.StringProperty;
11 |
12 | /**
13 | * Model class for a Person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class Person {
18 |
19 | private final StringProperty firstName;
20 | private final StringProperty lastName;
21 | private final StringProperty street;
22 | private final IntegerProperty postalCode;
23 | private final StringProperty city;
24 | private final ObjectProperty birthday;
25 |
26 | /**
27 | * Default constructor.
28 | */
29 | public Person() {
30 | this(null, null);
31 | }
32 |
33 | /**
34 | * Constructor with some initial data.
35 | *
36 | * @param firstName
37 | * @param lastName
38 | */
39 | public Person(String firstName, String lastName) {
40 | this.firstName = new SimpleStringProperty(firstName);
41 | this.lastName = new SimpleStringProperty(lastName);
42 |
43 | // Some initial dummy data, just for convenient testing.
44 | this.street = new SimpleStringProperty("some street");
45 | this.postalCode = new SimpleIntegerProperty(1234);
46 | this.city = new SimpleStringProperty("some city");
47 | this.birthday = new SimpleObjectProperty(LocalDate.of(1999, 2, 21));
48 | }
49 |
50 | public String getFirstName() {
51 | return firstName.get();
52 | }
53 |
54 | public void setFirstName(String firstName) {
55 | this.firstName.set(firstName);
56 | }
57 |
58 | public StringProperty firstNameProperty() {
59 | return firstName;
60 | }
61 |
62 | public String getLastName() {
63 | return lastName.get();
64 | }
65 |
66 | public void setLastName(String lastName) {
67 | this.lastName.set(lastName);
68 | }
69 |
70 | public StringProperty lastNameProperty() {
71 | return lastName;
72 | }
73 |
74 | public String getStreet() {
75 | return street.get();
76 | }
77 |
78 | public void setStreet(String street) {
79 | this.street.set(street);
80 | }
81 |
82 | public StringProperty streetProperty() {
83 | return street;
84 | }
85 |
86 | public int getPostalCode() {
87 | return postalCode.get();
88 | }
89 |
90 | public void setPostalCode(int postalCode) {
91 | this.postalCode.set(postalCode);
92 | }
93 |
94 | public IntegerProperty postalCodeProperty() {
95 | return postalCode;
96 | }
97 |
98 | public String getCity() {
99 | return city.get();
100 | }
101 |
102 | public void setCity(String city) {
103 | this.city.set(city);
104 | }
105 |
106 | public StringProperty cityProperty() {
107 | return city;
108 | }
109 |
110 | public LocalDate getBirthday() {
111 | return birthday.get();
112 | }
113 |
114 | public void setBirthday(LocalDate birthday) {
115 | this.birthday.set(birthday);
116 | }
117 |
118 | public ObjectProperty birthdayProperty() {
119 | return birthday;
120 | }
121 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/model/Person.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleObjectProperty;
9 | import javafx.beans.property.SimpleStringProperty;
10 | import javafx.beans.property.StringProperty;
11 |
12 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
13 |
14 | import ch.makery.address.util.LocalDateAdapter;
15 |
16 | /**
17 | * Model class for a Person.
18 | *
19 | * @author Marco Jakob
20 | */
21 | public class Person {
22 |
23 | private final StringProperty firstName;
24 | private final StringProperty lastName;
25 | private final StringProperty street;
26 | private final IntegerProperty postalCode;
27 | private final StringProperty city;
28 | private final ObjectProperty birthday;
29 |
30 | /**
31 | * Default constructor.
32 | */
33 | public Person() {
34 | this(null, null);
35 | }
36 |
37 | /**
38 | * Constructor with some initial data.
39 | *
40 | * @param firstName
41 | * @param lastName
42 | */
43 | public Person(String firstName, String lastName) {
44 | this.firstName = new SimpleStringProperty(firstName);
45 | this.lastName = new SimpleStringProperty(lastName);
46 |
47 | // Some initial dummy data, just for convenient testing.
48 | this.street = new SimpleStringProperty("some street");
49 | this.postalCode = new SimpleIntegerProperty(1234);
50 | this.city = new SimpleStringProperty("some city");
51 | this.birthday = new SimpleObjectProperty(LocalDate.of(1999, 2, 21));
52 | }
53 |
54 | public String getFirstName() {
55 | return firstName.get();
56 | }
57 |
58 | public void setFirstName(String firstName) {
59 | this.firstName.set(firstName);
60 | }
61 |
62 | public StringProperty firstNameProperty() {
63 | return firstName;
64 | }
65 |
66 | public String getLastName() {
67 | return lastName.get();
68 | }
69 |
70 | public void setLastName(String lastName) {
71 | this.lastName.set(lastName);
72 | }
73 |
74 | public StringProperty lastNameProperty() {
75 | return lastName;
76 | }
77 |
78 | public String getStreet() {
79 | return street.get();
80 | }
81 |
82 | public void setStreet(String street) {
83 | this.street.set(street);
84 | }
85 |
86 | public StringProperty streetProperty() {
87 | return street;
88 | }
89 |
90 | public int getPostalCode() {
91 | return postalCode.get();
92 | }
93 |
94 | public void setPostalCode(int postalCode) {
95 | this.postalCode.set(postalCode);
96 | }
97 |
98 | public IntegerProperty postalCodeProperty() {
99 | return postalCode;
100 | }
101 |
102 | public String getCity() {
103 | return city.get();
104 | }
105 |
106 | public void setCity(String city) {
107 | this.city.set(city);
108 | }
109 |
110 | public StringProperty cityProperty() {
111 | return city;
112 | }
113 |
114 | @XmlJavaTypeAdapter(LocalDateAdapter.class)
115 | public LocalDate getBirthday() {
116 | return birthday.get();
117 | }
118 |
119 | public void setBirthday(LocalDate birthday) {
120 | this.birthday.set(birthday);
121 | }
122 |
123 | public ObjectProperty birthdayProperty() {
124 | return birthday;
125 | }
126 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/model/Person.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleObjectProperty;
9 | import javafx.beans.property.SimpleStringProperty;
10 | import javafx.beans.property.StringProperty;
11 |
12 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
13 |
14 | import ch.makery.address.util.LocalDateAdapter;
15 |
16 | /**
17 | * Model class for a Person.
18 | *
19 | * @author Marco Jakob
20 | */
21 | public class Person {
22 |
23 | private final StringProperty firstName;
24 | private final StringProperty lastName;
25 | private final StringProperty street;
26 | private final IntegerProperty postalCode;
27 | private final StringProperty city;
28 | private final ObjectProperty birthday;
29 |
30 | /**
31 | * Default constructor.
32 | */
33 | public Person() {
34 | this(null, null);
35 | }
36 |
37 | /**
38 | * Constructor with some initial data.
39 | *
40 | * @param firstName
41 | * @param lastName
42 | */
43 | public Person(String firstName, String lastName) {
44 | this.firstName = new SimpleStringProperty(firstName);
45 | this.lastName = new SimpleStringProperty(lastName);
46 |
47 | // Some initial dummy data, just for convenient testing.
48 | this.street = new SimpleStringProperty("some street");
49 | this.postalCode = new SimpleIntegerProperty(1234);
50 | this.city = new SimpleStringProperty("some city");
51 | this.birthday = new SimpleObjectProperty(LocalDate.of(1999, 2, 21));
52 | }
53 |
54 | public String getFirstName() {
55 | return firstName.get();
56 | }
57 |
58 | public void setFirstName(String firstName) {
59 | this.firstName.set(firstName);
60 | }
61 |
62 | public StringProperty firstNameProperty() {
63 | return firstName;
64 | }
65 |
66 | public String getLastName() {
67 | return lastName.get();
68 | }
69 |
70 | public void setLastName(String lastName) {
71 | this.lastName.set(lastName);
72 | }
73 |
74 | public StringProperty lastNameProperty() {
75 | return lastName;
76 | }
77 |
78 | public String getStreet() {
79 | return street.get();
80 | }
81 |
82 | public void setStreet(String street) {
83 | this.street.set(street);
84 | }
85 |
86 | public StringProperty streetProperty() {
87 | return street;
88 | }
89 |
90 | public int getPostalCode() {
91 | return postalCode.get();
92 | }
93 |
94 | public void setPostalCode(int postalCode) {
95 | this.postalCode.set(postalCode);
96 | }
97 |
98 | public IntegerProperty postalCodeProperty() {
99 | return postalCode;
100 | }
101 |
102 | public String getCity() {
103 | return city.get();
104 | }
105 |
106 | public void setCity(String city) {
107 | this.city.set(city);
108 | }
109 |
110 | public StringProperty cityProperty() {
111 | return city;
112 | }
113 |
114 | @XmlJavaTypeAdapter(LocalDateAdapter.class)
115 | public LocalDate getBirthday() {
116 | return birthday.get();
117 | }
118 |
119 | public void setBirthday(LocalDate birthday) {
120 | this.birthday.set(birthday);
121 | }
122 |
123 | public ObjectProperty birthdayProperty() {
124 | return birthday;
125 | }
126 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/model/Person.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.model;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javafx.beans.property.IntegerProperty;
6 | import javafx.beans.property.ObjectProperty;
7 | import javafx.beans.property.SimpleIntegerProperty;
8 | import javafx.beans.property.SimpleObjectProperty;
9 | import javafx.beans.property.SimpleStringProperty;
10 | import javafx.beans.property.StringProperty;
11 |
12 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
13 |
14 | import ch.makery.address.util.LocalDateAdapter;
15 |
16 | /**
17 | * Model class for a Person.
18 | *
19 | * @author Marco Jakob
20 | */
21 | public class Person {
22 |
23 | private final StringProperty firstName;
24 | private final StringProperty lastName;
25 | private final StringProperty street;
26 | private final IntegerProperty postalCode;
27 | private final StringProperty city;
28 | private final ObjectProperty birthday;
29 |
30 | /**
31 | * Default constructor.
32 | */
33 | public Person() {
34 | this(null, null);
35 | }
36 |
37 | /**
38 | * Constructor with some initial data.
39 | *
40 | * @param firstName
41 | * @param lastName
42 | */
43 | public Person(String firstName, String lastName) {
44 | this.firstName = new SimpleStringProperty(firstName);
45 | this.lastName = new SimpleStringProperty(lastName);
46 |
47 | // Some initial dummy data, just for convenient testing.
48 | this.street = new SimpleStringProperty("some street");
49 | this.postalCode = new SimpleIntegerProperty(1234);
50 | this.city = new SimpleStringProperty("some city");
51 | this.birthday = new SimpleObjectProperty(LocalDate.of(1999, 2, 21));
52 | }
53 |
54 | public String getFirstName() {
55 | return firstName.get();
56 | }
57 |
58 | public void setFirstName(String firstName) {
59 | this.firstName.set(firstName);
60 | }
61 |
62 | public StringProperty firstNameProperty() {
63 | return firstName;
64 | }
65 |
66 | public String getLastName() {
67 | return lastName.get();
68 | }
69 |
70 | public void setLastName(String lastName) {
71 | this.lastName.set(lastName);
72 | }
73 |
74 | public StringProperty lastNameProperty() {
75 | return lastName;
76 | }
77 |
78 | public String getStreet() {
79 | return street.get();
80 | }
81 |
82 | public void setStreet(String street) {
83 | this.street.set(street);
84 | }
85 |
86 | public StringProperty streetProperty() {
87 | return street;
88 | }
89 |
90 | public int getPostalCode() {
91 | return postalCode.get();
92 | }
93 |
94 | public void setPostalCode(int postalCode) {
95 | this.postalCode.set(postalCode);
96 | }
97 |
98 | public IntegerProperty postalCodeProperty() {
99 | return postalCode;
100 | }
101 |
102 | public String getCity() {
103 | return city.get();
104 | }
105 |
106 | public void setCity(String city) {
107 | this.city.set(city);
108 | }
109 |
110 | public StringProperty cityProperty() {
111 | return city;
112 | }
113 |
114 | @XmlJavaTypeAdapter(LocalDateAdapter.class)
115 | public LocalDate getBirthday() {
116 | return birthday.get();
117 | }
118 |
119 | public void setBirthday(LocalDate birthday) {
120 | this.birthday.set(birthday);
121 | }
122 |
123 | public ObjectProperty birthdayProperty() {
124 | return birthday;
125 | }
126 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/view/RootLayoutController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import java.io.File;
4 |
5 | import javafx.fxml.FXML;
6 | import javafx.scene.control.Alert;
7 | import javafx.scene.control.Alert.AlertType;
8 | import javafx.stage.FileChooser;
9 | import ch.makery.address.MainApp;
10 |
11 | /**
12 | * The controller for the root layout. The root layout provides the basic
13 | * application layout containing a menu bar and space where other JavaFX
14 | * elements can be placed.
15 | *
16 | * @author Marco Jakob
17 | */
18 | public class RootLayoutController {
19 |
20 | // Reference to the main application
21 | private MainApp mainApp;
22 |
23 | /**
24 | * Is called by the main application to give a reference back to itself.
25 | *
26 | * @param mainApp
27 | */
28 | public void setMainApp(MainApp mainApp) {
29 | this.mainApp = mainApp;
30 | }
31 |
32 | /**
33 | * Creates an empty address book.
34 | */
35 | @FXML
36 | private void handleNew() {
37 | mainApp.getPersonData().clear();
38 | mainApp.setPersonFilePath(null);
39 | }
40 |
41 | /**
42 | * Opens a FileChooser to let the user select an address book to load.
43 | */
44 | @FXML
45 | private void handleOpen() {
46 | FileChooser fileChooser = new FileChooser();
47 |
48 | // Set extension filter
49 | FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
50 | "XML files (*.xml)", "*.xml");
51 | fileChooser.getExtensionFilters().add(extFilter);
52 |
53 | // Show save file dialog
54 | File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
55 |
56 | if (file != null) {
57 | mainApp.loadPersonDataFromFile(file);
58 | }
59 | }
60 |
61 | /**
62 | * Saves the file to the person file that is currently open. If there is no
63 | * open file, the "save as" dialog is shown.
64 | */
65 | @FXML
66 | private void handleSave() {
67 | File personFile = mainApp.getPersonFilePath();
68 | if (personFile != null) {
69 | mainApp.savePersonDataToFile(personFile);
70 | } else {
71 | handleSaveAs();
72 | }
73 | }
74 |
75 | /**
76 | * Opens a FileChooser to let the user select a file to save to.
77 | */
78 | @FXML
79 | private void handleSaveAs() {
80 | FileChooser fileChooser = new FileChooser();
81 |
82 | // Set extension filter
83 | FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
84 | "XML files (*.xml)", "*.xml");
85 | fileChooser.getExtensionFilters().add(extFilter);
86 |
87 | // Show save file dialog
88 | File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
89 |
90 | if (file != null) {
91 | // Make sure it has the correct extension
92 | if (!file.getPath().endsWith(".xml")) {
93 | file = new File(file.getPath() + ".xml");
94 | }
95 | mainApp.savePersonDataToFile(file);
96 | }
97 | }
98 |
99 | /**
100 | * Opens an about dialog.
101 | */
102 | @FXML
103 | private void handleAbout() {
104 | Alert alert = new Alert(AlertType.INFORMATION);
105 | alert.setTitle("AddressApp");
106 | alert.setHeaderText("About");
107 | alert.setContentText("Author: Marco Jakob\nWebsite: http://code.makery.ch");
108 |
109 | alert.showAndWait();
110 | }
111 |
112 | /**
113 | * Closes the application.
114 | */
115 | @FXML
116 | private void handleExit() {
117 | System.exit(0);
118 | }
119 | }
--------------------------------------------------------------------------------
/AddressApp-Part-2/src/ch/makery/address/MainApp.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address;
2 |
3 | import java.io.IOException;
4 |
5 | import javafx.application.Application;
6 | import javafx.collections.FXCollections;
7 | import javafx.collections.ObservableList;
8 | import javafx.fxml.FXMLLoader;
9 | import javafx.scene.Scene;
10 | import javafx.scene.layout.AnchorPane;
11 | import javafx.scene.layout.BorderPane;
12 | import javafx.stage.Stage;
13 | import ch.makery.address.model.Person;
14 | import ch.makery.address.view.PersonOverviewController;
15 |
16 | public class MainApp extends Application {
17 |
18 | private Stage primaryStage;
19 | private BorderPane rootLayout;
20 |
21 | /**
22 | * The data as an observable list of Persons.
23 | */
24 | private ObservableList personData = FXCollections.observableArrayList();
25 |
26 | /**
27 | * Constructor
28 | */
29 | public MainApp() {
30 | // Add some sample data
31 | personData.add(new Person("Hans", "Muster"));
32 | personData.add(new Person("Ruth", "Mueller"));
33 | personData.add(new Person("Heinz", "Kurz"));
34 | personData.add(new Person("Cornelia", "Meier"));
35 | personData.add(new Person("Werner", "Meyer"));
36 | personData.add(new Person("Lydia", "Kunz"));
37 | personData.add(new Person("Anna", "Best"));
38 | personData.add(new Person("Stefan", "Meier"));
39 | personData.add(new Person("Martin", "Mueller"));
40 | }
41 |
42 | /**
43 | * Returns the data as an observable list of Persons.
44 | * @return
45 | */
46 | public ObservableList getPersonData() {
47 | return personData;
48 | }
49 |
50 | @Override
51 | public void start(Stage primaryStage) {
52 | this.primaryStage = primaryStage;
53 | this.primaryStage.setTitle("AddressApp");
54 |
55 | initRootLayout();
56 |
57 | showPersonOverview();
58 | }
59 |
60 | /**
61 | * Initializes the root layout.
62 | */
63 | public void initRootLayout() {
64 | try {
65 | // Load root layout from fxml file.
66 | FXMLLoader loader = new FXMLLoader();
67 | loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
68 | rootLayout = (BorderPane) loader.load();
69 |
70 | // Show the scene containing the root layout.
71 | Scene scene = new Scene(rootLayout);
72 | primaryStage.setScene(scene);
73 | primaryStage.show();
74 | } catch (IOException e) {
75 | e.printStackTrace();
76 | }
77 | }
78 |
79 | /**
80 | * Shows the person overview inside the root layout.
81 | */
82 | public void showPersonOverview() {
83 | try {
84 | // Load person overview.
85 | FXMLLoader loader = new FXMLLoader();
86 | loader.setLocation(MainApp.class.getResource("view/PersonOverview.fxml"));
87 | AnchorPane personOverview = (AnchorPane) loader.load();
88 |
89 | // Set person overview into the center of root layout.
90 | rootLayout.setCenter(personOverview);
91 |
92 | // Give the controller access to the main app.
93 | PersonOverviewController controller = loader.getController();
94 | controller.setMainApp(this);
95 |
96 | } catch (IOException e) {
97 | e.printStackTrace();
98 | }
99 | }
100 |
101 | /**
102 | * Returns the main stage.
103 | * @return
104 | */
105 | public Stage getPrimaryStage() {
106 | return primaryStage;
107 | }
108 |
109 | public static void main(String[] args) {
110 | launch(args);
111 | }
112 | }
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/view/DarkTheme.css:
--------------------------------------------------------------------------------
1 | .background {
2 | -fx-background-color: #1d1d1d;
3 | }
4 |
5 | .label {
6 | -fx-font-size: 11pt;
7 | -fx-font-family: "Segoe UI Semibold";
8 | -fx-text-fill: white;
9 | -fx-opacity: 0.6;
10 | }
11 |
12 | .label-bright {
13 | -fx-font-size: 11pt;
14 | -fx-font-family: "Segoe UI Semibold";
15 | -fx-text-fill: white;
16 | -fx-opacity: 1;
17 | }
18 |
19 | .label-header {
20 | -fx-font-size: 32pt;
21 | -fx-font-family: "Segoe UI Light";
22 | -fx-text-fill: white;
23 | -fx-opacity: 1;
24 | }
25 |
26 | .table-view {
27 | -fx-base: #1d1d1d;
28 | -fx-control-inner-background: #1d1d1d;
29 | -fx-background-color: #1d1d1d;
30 | -fx-table-cell-border-color: transparent;
31 | -fx-table-header-border-color: transparent;
32 | -fx-padding: 5;
33 | }
34 |
35 | .table-view .column-header-background {
36 | -fx-background-color: transparent;
37 | }
38 |
39 | .table-view .column-header, .table-view .filler {
40 | -fx-size: 35;
41 | -fx-border-width: 0 0 1 0;
42 | -fx-background-color: transparent;
43 | -fx-border-color:
44 | transparent
45 | transparent
46 | derive(-fx-base, 80%)
47 | transparent;
48 | -fx-border-insets: 0 10 1 0;
49 | }
50 |
51 | .table-view .column-header .label {
52 | -fx-font-size: 20pt;
53 | -fx-font-family: "Segoe UI Light";
54 | -fx-text-fill: white;
55 | -fx-alignment: center-left;
56 | -fx-opacity: 1;
57 | }
58 |
59 | .table-view:focused .table-row-cell:filled:focused:selected {
60 | -fx-background-color: -fx-focus-color;
61 | }
62 |
63 | .split-pane:horizontal > .split-pane-divider {
64 | -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
65 | -fx-background-color: transparent, derive(#1d1d1d,20%);
66 | }
67 |
68 | .split-pane {
69 | -fx-padding: 1 0 0 0;
70 | }
71 |
72 | .menu-bar {
73 | -fx-background-color: derive(#1d1d1d,20%);
74 | }
75 |
76 | .context-menu {
77 | -fx-background-color: derive(#1d1d1d,50%);
78 | }
79 |
80 | .menu-bar .label {
81 | -fx-font-size: 14pt;
82 | -fx-font-family: "Segoe UI Light";
83 | -fx-text-fill: white;
84 | -fx-opacity: 0.9;
85 | }
86 |
87 | .menu .left-container {
88 | -fx-background-color: black;
89 | }
90 |
91 | .text-field {
92 | -fx-font-size: 12pt;
93 | -fx-font-family: "Segoe UI Semibold";
94 | }
95 |
96 | /*
97 | * Metro style Push Button
98 | * Author: Pedro Duque Vieira
99 | * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
100 | */
101 | .button {
102 | -fx-padding: 5 22 5 22;
103 | -fx-border-color: #e2e2e2;
104 | -fx-border-width: 2;
105 | -fx-background-radius: 0;
106 | -fx-background-color: #1d1d1d;
107 | -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
108 | -fx-font-size: 11pt;
109 | -fx-text-fill: #d8d8d8;
110 | -fx-background-insets: 0 0 0 0, 0, 1, 2;
111 | }
112 |
113 | .button:hover {
114 | -fx-background-color: #3a3a3a;
115 | }
116 |
117 | .button:pressed, .button:default:hover:pressed {
118 | -fx-background-color: white;
119 | -fx-text-fill: #1d1d1d;
120 | }
121 |
122 | .button:focused {
123 | -fx-border-color: white, white;
124 | -fx-border-width: 1, 1;
125 | -fx-border-style: solid, segments(1, 1);
126 | -fx-border-radius: 0, 0;
127 | -fx-border-insets: 1 1 1 1, 0;
128 | }
129 |
130 | .button:disabled, .button:default:disabled {
131 | -fx-opacity: 0.4;
132 | -fx-background-color: #1d1d1d;
133 | -fx-text-fill: white;
134 | }
135 |
136 | .button:default {
137 | -fx-background-color: -fx-focus-color;
138 | -fx-text-fill: #ffffff;
139 | }
140 |
141 | .button:default:hover {
142 | -fx-background-color: derive(-fx-focus-color,30%);
143 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/view/DarkTheme.css:
--------------------------------------------------------------------------------
1 | .background {
2 | -fx-background-color: #1d1d1d;
3 | }
4 |
5 | .label {
6 | -fx-font-size: 11pt;
7 | -fx-font-family: "Segoe UI Semibold";
8 | -fx-text-fill: white;
9 | -fx-opacity: 0.6;
10 | }
11 |
12 | .label-bright {
13 | -fx-font-size: 11pt;
14 | -fx-font-family: "Segoe UI Semibold";
15 | -fx-text-fill: white;
16 | -fx-opacity: 1;
17 | }
18 |
19 | .label-header {
20 | -fx-font-size: 32pt;
21 | -fx-font-family: "Segoe UI Light";
22 | -fx-text-fill: white;
23 | -fx-opacity: 1;
24 | }
25 |
26 | .table-view {
27 | -fx-base: #1d1d1d;
28 | -fx-control-inner-background: #1d1d1d;
29 | -fx-background-color: #1d1d1d;
30 | -fx-table-cell-border-color: transparent;
31 | -fx-table-header-border-color: transparent;
32 | -fx-padding: 5;
33 | }
34 |
35 | .table-view .column-header-background {
36 | -fx-background-color: transparent;
37 | }
38 |
39 | .table-view .column-header, .table-view .filler {
40 | -fx-size: 35;
41 | -fx-border-width: 0 0 1 0;
42 | -fx-background-color: transparent;
43 | -fx-border-color:
44 | transparent
45 | transparent
46 | derive(-fx-base, 80%)
47 | transparent;
48 | -fx-border-insets: 0 10 1 0;
49 | }
50 |
51 | .table-view .column-header .label {
52 | -fx-font-size: 20pt;
53 | -fx-font-family: "Segoe UI Light";
54 | -fx-text-fill: white;
55 | -fx-alignment: center-left;
56 | -fx-opacity: 1;
57 | }
58 |
59 | .table-view:focused .table-row-cell:filled:focused:selected {
60 | -fx-background-color: -fx-focus-color;
61 | }
62 |
63 | .split-pane:horizontal > .split-pane-divider {
64 | -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
65 | -fx-background-color: transparent, derive(#1d1d1d,20%);
66 | }
67 |
68 | .split-pane {
69 | -fx-padding: 1 0 0 0;
70 | }
71 |
72 | .menu-bar {
73 | -fx-background-color: derive(#1d1d1d,20%);
74 | }
75 |
76 | .context-menu {
77 | -fx-background-color: derive(#1d1d1d,50%);
78 | }
79 |
80 | .menu-bar .label {
81 | -fx-font-size: 14pt;
82 | -fx-font-family: "Segoe UI Light";
83 | -fx-text-fill: white;
84 | -fx-opacity: 0.9;
85 | }
86 |
87 | .menu .left-container {
88 | -fx-background-color: black;
89 | }
90 |
91 | .text-field {
92 | -fx-font-size: 12pt;
93 | -fx-font-family: "Segoe UI Semibold";
94 | }
95 |
96 | /*
97 | * Metro style Push Button
98 | * Author: Pedro Duque Vieira
99 | * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
100 | */
101 | .button {
102 | -fx-padding: 5 22 5 22;
103 | -fx-border-color: #e2e2e2;
104 | -fx-border-width: 2;
105 | -fx-background-radius: 0;
106 | -fx-background-color: #1d1d1d;
107 | -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
108 | -fx-font-size: 11pt;
109 | -fx-text-fill: #d8d8d8;
110 | -fx-background-insets: 0 0 0 0, 0, 1, 2;
111 | }
112 |
113 | .button:hover {
114 | -fx-background-color: #3a3a3a;
115 | }
116 |
117 | .button:pressed, .button:default:hover:pressed {
118 | -fx-background-color: white;
119 | -fx-text-fill: #1d1d1d;
120 | }
121 |
122 | .button:focused {
123 | -fx-border-color: white, white;
124 | -fx-border-width: 1, 1;
125 | -fx-border-style: solid, segments(1, 1);
126 | -fx-border-radius: 0, 0;
127 | -fx-border-insets: 1 1 1 1, 0;
128 | }
129 |
130 | .button:disabled, .button:default:disabled {
131 | -fx-opacity: 0.4;
132 | -fx-background-color: #1d1d1d;
133 | -fx-text-fill: white;
134 | }
135 |
136 | .button:default {
137 | -fx-background-color: -fx-focus-color;
138 | -fx-text-fill: #ffffff;
139 | }
140 |
141 | .button:default:hover {
142 | -fx-background-color: derive(-fx-focus-color,30%);
143 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/DarkTheme.css:
--------------------------------------------------------------------------------
1 | .background {
2 | -fx-background-color: #1d1d1d;
3 | }
4 |
5 | .label {
6 | -fx-font-size: 11pt;
7 | -fx-font-family: "Segoe UI Semibold";
8 | -fx-text-fill: white;
9 | -fx-opacity: 0.6;
10 | }
11 |
12 | .label-bright {
13 | -fx-font-size: 11pt;
14 | -fx-font-family: "Segoe UI Semibold";
15 | -fx-text-fill: white;
16 | -fx-opacity: 1;
17 | }
18 |
19 | .label-header {
20 | -fx-font-size: 32pt;
21 | -fx-font-family: "Segoe UI Light";
22 | -fx-text-fill: white;
23 | -fx-opacity: 1;
24 | }
25 |
26 | .table-view {
27 | -fx-base: #1d1d1d;
28 | -fx-control-inner-background: #1d1d1d;
29 | -fx-background-color: #1d1d1d;
30 | -fx-table-cell-border-color: transparent;
31 | -fx-table-header-border-color: transparent;
32 | -fx-padding: 5;
33 | }
34 |
35 | .table-view .column-header-background {
36 | -fx-background-color: transparent;
37 | }
38 |
39 | .table-view .column-header, .table-view .filler {
40 | -fx-size: 35;
41 | -fx-border-width: 0 0 1 0;
42 | -fx-background-color: transparent;
43 | -fx-border-color:
44 | transparent
45 | transparent
46 | derive(-fx-base, 80%)
47 | transparent;
48 | -fx-border-insets: 0 10 1 0;
49 | }
50 |
51 | .table-view .column-header .label {
52 | -fx-font-size: 20pt;
53 | -fx-font-family: "Segoe UI Light";
54 | -fx-text-fill: white;
55 | -fx-alignment: center-left;
56 | -fx-opacity: 1;
57 | }
58 |
59 | .table-view:focused .table-row-cell:filled:focused:selected {
60 | -fx-background-color: -fx-focus-color;
61 | }
62 |
63 | .split-pane:horizontal > .split-pane-divider {
64 | -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
65 | -fx-background-color: transparent, derive(#1d1d1d,20%);
66 | }
67 |
68 | .split-pane {
69 | -fx-padding: 1 0 0 0;
70 | }
71 |
72 | .menu-bar {
73 | -fx-background-color: derive(#1d1d1d,20%);
74 | }
75 |
76 | .context-menu {
77 | -fx-background-color: derive(#1d1d1d,50%);
78 | }
79 |
80 | .menu-bar .label {
81 | -fx-font-size: 14pt;
82 | -fx-font-family: "Segoe UI Light";
83 | -fx-text-fill: white;
84 | -fx-opacity: 0.9;
85 | }
86 |
87 | .menu .left-container {
88 | -fx-background-color: black;
89 | }
90 |
91 | .text-field {
92 | -fx-font-size: 12pt;
93 | -fx-font-family: "Segoe UI Semibold";
94 | }
95 |
96 | /*
97 | * Metro style Push Button
98 | * Author: Pedro Duque Vieira
99 | * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
100 | */
101 | .button {
102 | -fx-padding: 5 22 5 22;
103 | -fx-border-color: #e2e2e2;
104 | -fx-border-width: 2;
105 | -fx-background-radius: 0;
106 | -fx-background-color: #1d1d1d;
107 | -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
108 | -fx-font-size: 11pt;
109 | -fx-text-fill: #d8d8d8;
110 | -fx-background-insets: 0 0 0 0, 0, 1, 2;
111 | }
112 |
113 | .button:hover {
114 | -fx-background-color: #3a3a3a;
115 | }
116 |
117 | .button:pressed, .button:default:hover:pressed {
118 | -fx-background-color: white;
119 | -fx-text-fill: #1d1d1d;
120 | }
121 |
122 | .button:focused {
123 | -fx-border-color: white, white;
124 | -fx-border-width: 1, 1;
125 | -fx-border-style: solid, segments(1, 1);
126 | -fx-border-radius: 0, 0;
127 | -fx-border-insets: 1 1 1 1, 0;
128 | }
129 |
130 | .button:disabled, .button:default:disabled {
131 | -fx-opacity: 0.4;
132 | -fx-background-color: #1d1d1d;
133 | -fx-text-fill: white;
134 | }
135 |
136 | .button:default {
137 | -fx-background-color: -fx-focus-color;
138 | -fx-text-fill: #ffffff;
139 | }
140 |
141 | .button:default:hover {
142 | -fx-background-color: derive(-fx-focus-color,30%);
143 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/DarkTheme.css:
--------------------------------------------------------------------------------
1 | .background {
2 | -fx-background-color: #1d1d1d;
3 | }
4 |
5 | .label {
6 | -fx-font-size: 11pt;
7 | -fx-font-family: "Segoe UI Semibold";
8 | -fx-text-fill: white;
9 | -fx-opacity: 0.6;
10 | }
11 |
12 | .label-bright {
13 | -fx-font-size: 11pt;
14 | -fx-font-family: "Segoe UI Semibold";
15 | -fx-text-fill: white;
16 | -fx-opacity: 1;
17 | }
18 |
19 | .label-header {
20 | -fx-font-size: 32pt;
21 | -fx-font-family: "Segoe UI Light";
22 | -fx-text-fill: white;
23 | -fx-opacity: 1;
24 | }
25 |
26 | .table-view {
27 | -fx-base: #1d1d1d;
28 | -fx-control-inner-background: #1d1d1d;
29 | -fx-background-color: #1d1d1d;
30 | -fx-table-cell-border-color: transparent;
31 | -fx-table-header-border-color: transparent;
32 | -fx-padding: 5;
33 | }
34 |
35 | .table-view .column-header-background {
36 | -fx-background-color: transparent;
37 | }
38 |
39 | .table-view .column-header, .table-view .filler {
40 | -fx-size: 35;
41 | -fx-border-width: 0 0 1 0;
42 | -fx-background-color: transparent;
43 | -fx-border-color:
44 | transparent
45 | transparent
46 | derive(-fx-base, 80%)
47 | transparent;
48 | -fx-border-insets: 0 10 1 0;
49 | }
50 |
51 | .table-view .column-header .label {
52 | -fx-font-size: 20pt;
53 | -fx-font-family: "Segoe UI Light";
54 | -fx-text-fill: white;
55 | -fx-alignment: center-left;
56 | -fx-opacity: 1;
57 | }
58 |
59 | .table-view:focused .table-row-cell:filled:focused:selected {
60 | -fx-background-color: -fx-focus-color;
61 | }
62 |
63 | .split-pane:horizontal > .split-pane-divider {
64 | -fx-border-color: transparent #1d1d1d transparent #1d1d1d;
65 | -fx-background-color: transparent, derive(#1d1d1d,20%);
66 | }
67 |
68 | .split-pane {
69 | -fx-padding: 1 0 0 0;
70 | }
71 |
72 | .menu-bar {
73 | -fx-background-color: derive(#1d1d1d,20%);
74 | }
75 |
76 | .context-menu {
77 | -fx-background-color: derive(#1d1d1d,50%);
78 | }
79 |
80 | .menu-bar .label {
81 | -fx-font-size: 14pt;
82 | -fx-font-family: "Segoe UI Light";
83 | -fx-text-fill: white;
84 | -fx-opacity: 0.9;
85 | }
86 |
87 | .menu .left-container {
88 | -fx-background-color: black;
89 | }
90 |
91 | .text-field {
92 | -fx-font-size: 12pt;
93 | -fx-font-family: "Segoe UI Semibold";
94 | }
95 |
96 | /*
97 | * Metro style Push Button
98 | * Author: Pedro Duque Vieira
99 | * http://pixelduke.wordpress.com/2012/10/23/jmetro-windows-8-controls-on-java/
100 | */
101 | .button {
102 | -fx-padding: 5 22 5 22;
103 | -fx-border-color: #e2e2e2;
104 | -fx-border-width: 2;
105 | -fx-background-radius: 0;
106 | -fx-background-color: #1d1d1d;
107 | -fx-font-family: "Segoe UI", Helvetica, Arial, sans-serif;
108 | -fx-font-size: 11pt;
109 | -fx-text-fill: #d8d8d8;
110 | -fx-background-insets: 0 0 0 0, 0, 1, 2;
111 | }
112 |
113 | .button:hover {
114 | -fx-background-color: #3a3a3a;
115 | }
116 |
117 | .button:pressed, .button:default:hover:pressed {
118 | -fx-background-color: white;
119 | -fx-text-fill: #1d1d1d;
120 | }
121 |
122 | .button:focused {
123 | -fx-border-color: white, white;
124 | -fx-border-width: 1, 1;
125 | -fx-border-style: solid, segments(1, 1);
126 | -fx-border-radius: 0, 0;
127 | -fx-border-insets: 1 1 1 1, 0;
128 | }
129 |
130 | .button:disabled, .button:default:disabled {
131 | -fx-opacity: 0.4;
132 | -fx-background-color: #1d1d1d;
133 | -fx-text-fill: white;
134 | }
135 |
136 | .button:default {
137 | -fx-background-color: -fx-focus-color;
138 | -fx-text-fill: #ffffff;
139 | }
140 |
141 | .button:default:hover {
142 | -fx-background-color: derive(-fx-focus-color,30%);
143 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/RootLayoutController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import java.io.File;
4 |
5 | import javafx.fxml.FXML;
6 | import javafx.scene.control.Alert;
7 | import javafx.scene.control.Alert.AlertType;
8 | import javafx.stage.FileChooser;
9 | import ch.makery.address.MainApp;
10 |
11 | /**
12 | * The controller for the root layout. The root layout provides the basic
13 | * application layout containing a menu bar and space where other JavaFX
14 | * elements can be placed.
15 | *
16 | * @author Marco Jakob
17 | */
18 | public class RootLayoutController {
19 |
20 | // Reference to the main application
21 | private MainApp mainApp;
22 |
23 | /**
24 | * Is called by the main application to give a reference back to itself.
25 | *
26 | * @param mainApp
27 | */
28 | public void setMainApp(MainApp mainApp) {
29 | this.mainApp = mainApp;
30 | }
31 |
32 | /**
33 | * Creates an empty address book.
34 | */
35 | @FXML
36 | private void handleNew() {
37 | mainApp.getPersonData().clear();
38 | mainApp.setPersonFilePath(null);
39 | }
40 |
41 | /**
42 | * Opens a FileChooser to let the user select an address book to load.
43 | */
44 | @FXML
45 | private void handleOpen() {
46 | FileChooser fileChooser = new FileChooser();
47 |
48 | // Set extension filter
49 | FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
50 | "XML files (*.xml)", "*.xml");
51 | fileChooser.getExtensionFilters().add(extFilter);
52 |
53 | // Show save file dialog
54 | File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
55 |
56 | if (file != null) {
57 | mainApp.loadPersonDataFromFile(file);
58 | }
59 | }
60 |
61 | /**
62 | * Saves the file to the person file that is currently open. If there is no
63 | * open file, the "save as" dialog is shown.
64 | */
65 | @FXML
66 | private void handleSave() {
67 | File personFile = mainApp.getPersonFilePath();
68 | if (personFile != null) {
69 | mainApp.savePersonDataToFile(personFile);
70 | } else {
71 | handleSaveAs();
72 | }
73 | }
74 |
75 | /**
76 | * Opens a FileChooser to let the user select a file to save to.
77 | */
78 | @FXML
79 | private void handleSaveAs() {
80 | FileChooser fileChooser = new FileChooser();
81 |
82 | // Set extension filter
83 | FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
84 | "XML files (*.xml)", "*.xml");
85 | fileChooser.getExtensionFilters().add(extFilter);
86 |
87 | // Show save file dialog
88 | File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
89 |
90 | if (file != null) {
91 | // Make sure it has the correct extension
92 | if (!file.getPath().endsWith(".xml")) {
93 | file = new File(file.getPath() + ".xml");
94 | }
95 | mainApp.savePersonDataToFile(file);
96 | }
97 | }
98 |
99 | /**
100 | * Opens an about dialog.
101 | */
102 | @FXML
103 | private void handleAbout() {
104 | Alert alert = new Alert(AlertType.INFORMATION);
105 | alert.setTitle("AddressApp");
106 | alert.setHeaderText("About");
107 | alert.setContentText("Author: Marco Jakob\nWebsite: http://code.makery.ch");
108 |
109 | alert.showAndWait();
110 | }
111 |
112 | /**
113 | * Closes the application.
114 | */
115 | @FXML
116 | private void handleExit() {
117 | System.exit(0);
118 | }
119 |
120 | /**
121 | * Opens the birthday statistics.
122 | */
123 | @FXML
124 | private void handleShowBirthdayStatistics() {
125 | mainApp.showBirthdayStatistics();
126 | }
127 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/RootLayoutController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import java.io.File;
4 |
5 | import javafx.fxml.FXML;
6 | import javafx.scene.control.Alert;
7 | import javafx.scene.control.Alert.AlertType;
8 | import javafx.stage.FileChooser;
9 | import ch.makery.address.MainApp;
10 |
11 | /**
12 | * The controller for the root layout. The root layout provides the basic
13 | * application layout containing a menu bar and space where other JavaFX
14 | * elements can be placed.
15 | *
16 | * @author Marco Jakob
17 | */
18 | public class RootLayoutController {
19 |
20 | // Reference to the main application
21 | private MainApp mainApp;
22 |
23 | /**
24 | * Is called by the main application to give a reference back to itself.
25 | *
26 | * @param mainApp
27 | */
28 | public void setMainApp(MainApp mainApp) {
29 | this.mainApp = mainApp;
30 | }
31 |
32 | /**
33 | * Creates an empty address book.
34 | */
35 | @FXML
36 | private void handleNew() {
37 | mainApp.getPersonData().clear();
38 | mainApp.setPersonFilePath(null);
39 | }
40 |
41 | /**
42 | * Opens a FileChooser to let the user select an address book to load.
43 | */
44 | @FXML
45 | private void handleOpen() {
46 | FileChooser fileChooser = new FileChooser();
47 |
48 | // Set extension filter
49 | FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
50 | "XML files (*.xml)", "*.xml");
51 | fileChooser.getExtensionFilters().add(extFilter);
52 |
53 | // Show save file dialog
54 | File file = fileChooser.showOpenDialog(mainApp.getPrimaryStage());
55 |
56 | if (file != null) {
57 | mainApp.loadPersonDataFromFile(file);
58 | }
59 | }
60 |
61 | /**
62 | * Saves the file to the person file that is currently open. If there is no
63 | * open file, the "save as" dialog is shown.
64 | */
65 | @FXML
66 | private void handleSave() {
67 | File personFile = mainApp.getPersonFilePath();
68 | if (personFile != null) {
69 | mainApp.savePersonDataToFile(personFile);
70 | } else {
71 | handleSaveAs();
72 | }
73 | }
74 |
75 | /**
76 | * Opens a FileChooser to let the user select a file to save to.
77 | */
78 | @FXML
79 | private void handleSaveAs() {
80 | FileChooser fileChooser = new FileChooser();
81 |
82 | // Set extension filter
83 | FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(
84 | "XML files (*.xml)", "*.xml");
85 | fileChooser.getExtensionFilters().add(extFilter);
86 |
87 | // Show save file dialog
88 | File file = fileChooser.showSaveDialog(mainApp.getPrimaryStage());
89 |
90 | if (file != null) {
91 | // Make sure it has the correct extension
92 | if (!file.getPath().endsWith(".xml")) {
93 | file = new File(file.getPath() + ".xml");
94 | }
95 | mainApp.savePersonDataToFile(file);
96 | }
97 | }
98 |
99 | /**
100 | * Opens an about dialog.
101 | */
102 | @FXML
103 | private void handleAbout() {
104 | Alert alert = new Alert(AlertType.INFORMATION);
105 | alert.setTitle("AddressApp");
106 | alert.setHeaderText("About");
107 | alert.setContentText("Author: Marco Jakob\nWebsite: http://code.makery.ch");
108 |
109 | alert.showAndWait();
110 | }
111 |
112 | /**
113 | * Closes the application.
114 | */
115 | @FXML
116 | private void handleExit() {
117 | System.exit(0);
118 | }
119 |
120 | /**
121 | * Opens the birthday statistics.
122 | */
123 | @FXML
124 | private void handleShowBirthdayStatistics() {
125 | mainApp.showBirthdayStatistics();
126 | }
127 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/build/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/AddressApp-Part-1/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-2/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/PersonOverview.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/view/PersonEditDialogController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.TextField;
7 | import javafx.stage.Stage;
8 | import ch.makery.address.model.Person;
9 | import ch.makery.address.util.DateUtil;
10 |
11 | /**
12 | * Dialog to edit details of a person.
13 | *
14 | * @author Marco Jakob
15 | */
16 | public class PersonEditDialogController {
17 |
18 | @FXML
19 | private TextField firstNameField;
20 | @FXML
21 | private TextField lastNameField;
22 | @FXML
23 | private TextField streetField;
24 | @FXML
25 | private TextField postalCodeField;
26 | @FXML
27 | private TextField cityField;
28 | @FXML
29 | private TextField birthdayField;
30 |
31 |
32 | private Stage dialogStage;
33 | private Person person;
34 | private boolean okClicked = false;
35 |
36 | /**
37 | * Initializes the controller class. This method is automatically called
38 | * after the fxml file has been loaded.
39 | */
40 | @FXML
41 | private void initialize() {
42 | }
43 |
44 | /**
45 | * Sets the stage of this dialog.
46 | *
47 | * @param dialogStage
48 | */
49 | public void setDialogStage(Stage dialogStage) {
50 | this.dialogStage = dialogStage;
51 | }
52 |
53 | /**
54 | * Sets the person to be edited in the dialog.
55 | *
56 | * @param person
57 | */
58 | public void setPerson(Person person) {
59 | this.person = person;
60 |
61 | firstNameField.setText(person.getFirstName());
62 | lastNameField.setText(person.getLastName());
63 | streetField.setText(person.getStreet());
64 | postalCodeField.setText(Integer.toString(person.getPostalCode()));
65 | cityField.setText(person.getCity());
66 | birthdayField.setText(DateUtil.format(person.getBirthday()));
67 | birthdayField.setPromptText("dd.mm.yyyy");
68 | }
69 |
70 | /**
71 | * Returns true if the user clicked OK, false otherwise.
72 | *
73 | * @return
74 | */
75 | public boolean isOkClicked() {
76 | return okClicked;
77 | }
78 |
79 | /**
80 | * Called when the user clicks ok.
81 | */
82 | @FXML
83 | private void handleOk() {
84 | if (isInputValid()) {
85 | person.setFirstName(firstNameField.getText());
86 | person.setLastName(lastNameField.getText());
87 | person.setStreet(streetField.getText());
88 | person.setPostalCode(Integer.parseInt(postalCodeField.getText()));
89 | person.setCity(cityField.getText());
90 | person.setBirthday(DateUtil.parse(birthdayField.getText()));
91 |
92 | okClicked = true;
93 | dialogStage.close();
94 | }
95 | }
96 |
97 | /**
98 | * Called when the user clicks cancel.
99 | */
100 | @FXML
101 | private void handleCancel() {
102 | dialogStage.close();
103 | }
104 |
105 | /**
106 | * Validates the user input in the text fields.
107 | *
108 | * @return true if the input is valid
109 | */
110 | private boolean isInputValid() {
111 | String errorMessage = "";
112 |
113 | if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {
114 | errorMessage += "No valid first name!\n";
115 | }
116 | if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {
117 | errorMessage += "No valid last name!\n";
118 | }
119 | if (streetField.getText() == null || streetField.getText().length() == 0) {
120 | errorMessage += "No valid street!\n";
121 | }
122 |
123 | if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {
124 | errorMessage += "No valid postal code!\n";
125 | } else {
126 | // try to parse the postal code into an int.
127 | try {
128 | Integer.parseInt(postalCodeField.getText());
129 | } catch (NumberFormatException e) {
130 | errorMessage += "No valid postal code (must be an integer)!\n";
131 | }
132 | }
133 |
134 | if (cityField.getText() == null || cityField.getText().length() == 0) {
135 | errorMessage += "No valid city!\n";
136 | }
137 |
138 | if (birthdayField.getText() == null || birthdayField.getText().length() == 0) {
139 | errorMessage += "No valid birthday!\n";
140 | } else {
141 | if (!DateUtil.validDate(birthdayField.getText())) {
142 | errorMessage += "No valid birthday. Use the format dd.mm.yyyy!\n";
143 | }
144 | }
145 |
146 | if (errorMessage.length() == 0) {
147 | return true;
148 | } else {
149 | // Show the error message.
150 | Alert alert = new Alert(AlertType.ERROR);
151 | alert.initOwner(dialogStage);
152 | alert.setTitle("Invalid Fields");
153 | alert.setHeaderText("Please correct invalid fields");
154 | alert.setContentText(errorMessage);
155 |
156 | alert.showAndWait();
157 |
158 | return false;
159 | }
160 | }
161 | }
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/view/PersonEditDialogController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.TextField;
7 | import javafx.scene.image.Image;
8 | import javafx.stage.Stage;
9 | import ch.makery.address.model.Person;
10 | import ch.makery.address.util.DateUtil;
11 |
12 | /**
13 | * Dialog to edit details of a person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class PersonEditDialogController {
18 |
19 | @FXML
20 | private TextField firstNameField;
21 | @FXML
22 | private TextField lastNameField;
23 | @FXML
24 | private TextField streetField;
25 | @FXML
26 | private TextField postalCodeField;
27 | @FXML
28 | private TextField cityField;
29 | @FXML
30 | private TextField birthdayField;
31 |
32 |
33 | private Stage dialogStage;
34 | private Person person;
35 | private boolean okClicked = false;
36 |
37 | /**
38 | * Initializes the controller class. This method is automatically called
39 | * after the fxml file has been loaded.
40 | */
41 | @FXML
42 | private void initialize() {
43 | }
44 |
45 | /**
46 | * Sets the stage of this dialog.
47 | *
48 | * @param dialogStage
49 | */
50 | public void setDialogStage(Stage dialogStage) {
51 | this.dialogStage = dialogStage;
52 | }
53 |
54 | /**
55 | * Sets the person to be edited in the dialog.
56 | *
57 | * @param person
58 | */
59 | public void setPerson(Person person) {
60 | this.person = person;
61 |
62 | firstNameField.setText(person.getFirstName());
63 | lastNameField.setText(person.getLastName());
64 | streetField.setText(person.getStreet());
65 | postalCodeField.setText(Integer.toString(person.getPostalCode()));
66 | cityField.setText(person.getCity());
67 | birthdayField.setText(DateUtil.format(person.getBirthday()));
68 | birthdayField.setPromptText("dd.mm.yyyy");
69 | }
70 |
71 | /**
72 | * Returns true if the user clicked OK, false otherwise.
73 | *
74 | * @return
75 | */
76 | public boolean isOkClicked() {
77 | return okClicked;
78 | }
79 |
80 | /**
81 | * Called when the user clicks ok.
82 | */
83 | @FXML
84 | private void handleOk() {
85 | if (isInputValid()) {
86 | person.setFirstName(firstNameField.getText());
87 | person.setLastName(lastNameField.getText());
88 | person.setStreet(streetField.getText());
89 | person.setPostalCode(Integer.parseInt(postalCodeField.getText()));
90 | person.setCity(cityField.getText());
91 | person.setBirthday(DateUtil.parse(birthdayField.getText()));
92 |
93 | okClicked = true;
94 | dialogStage.close();
95 | }
96 | }
97 |
98 | /**
99 | * Called when the user clicks cancel.
100 | */
101 | @FXML
102 | private void handleCancel() {
103 | dialogStage.close();
104 | }
105 |
106 | /**
107 | * Validates the user input in the text fields.
108 | *
109 | * @return true if the input is valid
110 | */
111 | private boolean isInputValid() {
112 | String errorMessage = "";
113 |
114 | if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {
115 | errorMessage += "No valid first name!\n";
116 | }
117 | if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {
118 | errorMessage += "No valid last name!\n";
119 | }
120 | if (streetField.getText() == null || streetField.getText().length() == 0) {
121 | errorMessage += "No valid street!\n";
122 | }
123 |
124 | if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {
125 | errorMessage += "No valid postal code!\n";
126 | } else {
127 | // try to parse the postal code into an int.
128 | try {
129 | Integer.parseInt(postalCodeField.getText());
130 | } catch (NumberFormatException e) {
131 | errorMessage += "No valid postal code (must be an integer)!\n";
132 | }
133 | }
134 |
135 | if (cityField.getText() == null || cityField.getText().length() == 0) {
136 | errorMessage += "No valid city!\n";
137 | }
138 |
139 | if (birthdayField.getText() == null || birthdayField.getText().length() == 0) {
140 | errorMessage += "No valid birthday!\n";
141 | } else {
142 | if (!DateUtil.validDate(birthdayField.getText())) {
143 | errorMessage += "No valid birthday. Use the format dd.mm.yyyy!\n";
144 | }
145 | }
146 |
147 | if (errorMessage.length() == 0) {
148 | return true;
149 | } else {
150 | // Show the error message.
151 | Alert alert = new Alert(AlertType.ERROR);
152 | alert.initOwner(dialogStage);
153 | alert.setTitle("Invalid Fields");
154 | alert.setHeaderText("Please correct invalid fields");
155 | alert.setContentText(errorMessage);
156 |
157 | alert.showAndWait();
158 |
159 | return false;
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/AddressApp-Part-5/src/ch/makery/address/view/PersonEditDialogController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.TextField;
7 | import javafx.scene.image.Image;
8 | import javafx.stage.Stage;
9 | import ch.makery.address.model.Person;
10 | import ch.makery.address.util.DateUtil;
11 |
12 | /**
13 | * Dialog to edit details of a person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class PersonEditDialogController {
18 |
19 | @FXML
20 | private TextField firstNameField;
21 | @FXML
22 | private TextField lastNameField;
23 | @FXML
24 | private TextField streetField;
25 | @FXML
26 | private TextField postalCodeField;
27 | @FXML
28 | private TextField cityField;
29 | @FXML
30 | private TextField birthdayField;
31 |
32 |
33 | private Stage dialogStage;
34 | private Person person;
35 | private boolean okClicked = false;
36 |
37 | /**
38 | * Initializes the controller class. This method is automatically called
39 | * after the fxml file has been loaded.
40 | */
41 | @FXML
42 | private void initialize() {
43 | }
44 |
45 | /**
46 | * Sets the stage of this dialog.
47 | *
48 | * @param dialogStage
49 | */
50 | public void setDialogStage(Stage dialogStage) {
51 | this.dialogStage = dialogStage;
52 | }
53 |
54 | /**
55 | * Sets the person to be edited in the dialog.
56 | *
57 | * @param person
58 | */
59 | public void setPerson(Person person) {
60 | this.person = person;
61 |
62 | firstNameField.setText(person.getFirstName());
63 | lastNameField.setText(person.getLastName());
64 | streetField.setText(person.getStreet());
65 | postalCodeField.setText(Integer.toString(person.getPostalCode()));
66 | cityField.setText(person.getCity());
67 | birthdayField.setText(DateUtil.format(person.getBirthday()));
68 | birthdayField.setPromptText("dd.mm.yyyy");
69 | }
70 |
71 | /**
72 | * Returns true if the user clicked OK, false otherwise.
73 | *
74 | * @return
75 | */
76 | public boolean isOkClicked() {
77 | return okClicked;
78 | }
79 |
80 | /**
81 | * Called when the user clicks ok.
82 | */
83 | @FXML
84 | private void handleOk() {
85 | if (isInputValid()) {
86 | person.setFirstName(firstNameField.getText());
87 | person.setLastName(lastNameField.getText());
88 | person.setStreet(streetField.getText());
89 | person.setPostalCode(Integer.parseInt(postalCodeField.getText()));
90 | person.setCity(cityField.getText());
91 | person.setBirthday(DateUtil.parse(birthdayField.getText()));
92 |
93 | okClicked = true;
94 | dialogStage.close();
95 | }
96 | }
97 |
98 | /**
99 | * Called when the user clicks cancel.
100 | */
101 | @FXML
102 | private void handleCancel() {
103 | dialogStage.close();
104 | }
105 |
106 | /**
107 | * Validates the user input in the text fields.
108 | *
109 | * @return true if the input is valid
110 | */
111 | private boolean isInputValid() {
112 | String errorMessage = "";
113 |
114 | if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {
115 | errorMessage += "No valid first name!\n";
116 | }
117 | if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {
118 | errorMessage += "No valid last name!\n";
119 | }
120 | if (streetField.getText() == null || streetField.getText().length() == 0) {
121 | errorMessage += "No valid street!\n";
122 | }
123 |
124 | if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {
125 | errorMessage += "No valid postal code!\n";
126 | } else {
127 | // try to parse the postal code into an int.
128 | try {
129 | Integer.parseInt(postalCodeField.getText());
130 | } catch (NumberFormatException e) {
131 | errorMessage += "No valid postal code (must be an integer)!\n";
132 | }
133 | }
134 |
135 | if (cityField.getText() == null || cityField.getText().length() == 0) {
136 | errorMessage += "No valid city!\n";
137 | }
138 |
139 | if (birthdayField.getText() == null || birthdayField.getText().length() == 0) {
140 | errorMessage += "No valid birthday!\n";
141 | } else {
142 | if (!DateUtil.validDate(birthdayField.getText())) {
143 | errorMessage += "No valid birthday. Use the format dd.mm.yyyy!\n";
144 | }
145 | }
146 |
147 | if (errorMessage.length() == 0) {
148 | return true;
149 | } else {
150 | // Show the error message.
151 | Alert alert = new Alert(AlertType.ERROR);
152 | alert.initOwner(dialogStage);
153 | alert.setTitle("Invalid Fields");
154 | alert.setHeaderText("Please correct invalid fields");
155 | alert.setContentText(errorMessage);
156 |
157 | alert.showAndWait();
158 |
159 | return false;
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/MainApp.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address;
2 |
3 | import java.io.IOException;
4 |
5 | import javafx.application.Application;
6 | import javafx.collections.FXCollections;
7 | import javafx.collections.ObservableList;
8 | import javafx.fxml.FXMLLoader;
9 | import javafx.scene.Scene;
10 | import javafx.scene.layout.AnchorPane;
11 | import javafx.scene.layout.BorderPane;
12 | import javafx.stage.Modality;
13 | import javafx.stage.Stage;
14 | import ch.makery.address.model.Person;
15 | import ch.makery.address.view.PersonEditDialogController;
16 | import ch.makery.address.view.PersonOverviewController;
17 |
18 | public class MainApp extends Application {
19 |
20 | private Stage primaryStage;
21 | private BorderPane rootLayout;
22 |
23 | /**
24 | * The data as an observable list of Persons.
25 | */
26 | private ObservableList personData = FXCollections.observableArrayList();
27 |
28 | /**
29 | * Constructor
30 | */
31 | public MainApp() {
32 | // Add some sample data
33 | personData.add(new Person("Hans", "Muster"));
34 | personData.add(new Person("Ruth", "Mueller"));
35 | personData.add(new Person("Heinz", "Kurz"));
36 | personData.add(new Person("Cornelia", "Meier"));
37 | personData.add(new Person("Werner", "Meyer"));
38 | personData.add(new Person("Lydia", "Kunz"));
39 | personData.add(new Person("Anna", "Best"));
40 | personData.add(new Person("Stefan", "Meier"));
41 | personData.add(new Person("Martin", "Mueller"));
42 | }
43 |
44 | /**
45 | * Returns the data as an observable list of Persons.
46 | * @return
47 | */
48 | public ObservableList getPersonData() {
49 | return personData;
50 | }
51 |
52 | @Override
53 | public void start(Stage primaryStage) {
54 | this.primaryStage = primaryStage;
55 | this.primaryStage.setTitle("AddressApp");
56 |
57 | initRootLayout();
58 |
59 | showPersonOverview();
60 | }
61 |
62 | /**
63 | * Initializes the root layout.
64 | */
65 | public void initRootLayout() {
66 | try {
67 | // Load root layout from fxml file.
68 | FXMLLoader loader = new FXMLLoader();
69 | loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
70 | rootLayout = (BorderPane) loader.load();
71 |
72 | // Show the scene containing the root layout.
73 | Scene scene = new Scene(rootLayout);
74 | primaryStage.setScene(scene);
75 | primaryStage.show();
76 | } catch (IOException e) {
77 | e.printStackTrace();
78 | }
79 | }
80 |
81 | /**
82 | * Shows the person overview inside the root layout.
83 | */
84 | public void showPersonOverview() {
85 | try {
86 | // Load person overview.
87 | FXMLLoader loader = new FXMLLoader();
88 | loader.setLocation(MainApp.class.getResource("view/PersonOverview.fxml"));
89 | AnchorPane personOverview = (AnchorPane) loader.load();
90 |
91 | // Set person overview into the center of root layout.
92 | rootLayout.setCenter(personOverview);
93 |
94 | // Give the controller access to the main app.
95 | PersonOverviewController controller = loader.getController();
96 | controller.setMainApp(this);
97 |
98 | } catch (IOException e) {
99 | e.printStackTrace();
100 | }
101 | }
102 |
103 | /**
104 | * Opens a dialog to edit details for the specified person. If the user
105 | * clicks OK, the changes are saved into the provided person object and true
106 | * is returned.
107 | *
108 | * @param person the person object to be edited
109 | * @return true if the user clicked OK, false otherwise.
110 | */
111 | public boolean showPersonEditDialog(Person person) {
112 | try {
113 | // Load the fxml file and create a new stage for the popup dialog.
114 | FXMLLoader loader = new FXMLLoader();
115 | loader.setLocation(MainApp.class.getResource("view/PersonEditDialog.fxml"));
116 | AnchorPane page = (AnchorPane) loader.load();
117 |
118 | // Create the dialog Stage.
119 | Stage dialogStage = new Stage();
120 | dialogStage.setTitle("Edit Person");
121 | dialogStage.initModality(Modality.WINDOW_MODAL);
122 | dialogStage.initOwner(primaryStage);
123 | Scene scene = new Scene(page);
124 | dialogStage.setScene(scene);
125 |
126 | // Set the person into the controller.
127 | PersonEditDialogController controller = loader.getController();
128 | controller.setDialogStage(dialogStage);
129 | controller.setPerson(person);
130 |
131 | // Show the dialog and wait until the user closes it
132 | dialogStage.showAndWait();
133 |
134 | return controller.isOkClicked();
135 | } catch (IOException e) {
136 | e.printStackTrace();
137 | return false;
138 | }
139 | }
140 |
141 | /**
142 | * Returns the main stage.
143 | * @return
144 | */
145 | public Stage getPrimaryStage() {
146 | return primaryStage;
147 | }
148 |
149 | public static void main(String[] args) {
150 | launch(args);
151 | }
152 | }
--------------------------------------------------------------------------------
/AddressApp-Part-6/src/ch/makery/address/view/PersonEditDialogController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.TextField;
7 | import javafx.scene.image.Image;
8 | import javafx.stage.Stage;
9 | import ch.makery.address.model.Person;
10 | import ch.makery.address.util.DateUtil;
11 |
12 | /**
13 | * Dialog to edit details of a person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class PersonEditDialogController {
18 |
19 | @FXML
20 | private TextField firstNameField;
21 | @FXML
22 | private TextField lastNameField;
23 | @FXML
24 | private TextField streetField;
25 | @FXML
26 | private TextField postalCodeField;
27 | @FXML
28 | private TextField cityField;
29 | @FXML
30 | private TextField birthdayField;
31 |
32 |
33 | private Stage dialogStage;
34 | private Person person;
35 | private boolean okClicked = false;
36 |
37 | /**
38 | * Initializes the controller class. This method is automatically called
39 | * after the fxml file has been loaded.
40 | */
41 | @FXML
42 | private void initialize() {
43 | }
44 |
45 | /**
46 | * Sets the stage of this dialog.
47 | *
48 | * @param dialogStage
49 | */
50 | public void setDialogStage(Stage dialogStage) {
51 | this.dialogStage = dialogStage;
52 |
53 | // Set the dialog icon.
54 | this.dialogStage.getIcons().add(new Image("file:resources/images/edit.png"));
55 | }
56 |
57 | /**
58 | * Sets the person to be edited in the dialog.
59 | *
60 | * @param person
61 | */
62 | public void setPerson(Person person) {
63 | this.person = person;
64 |
65 | firstNameField.setText(person.getFirstName());
66 | lastNameField.setText(person.getLastName());
67 | streetField.setText(person.getStreet());
68 | postalCodeField.setText(Integer.toString(person.getPostalCode()));
69 | cityField.setText(person.getCity());
70 | birthdayField.setText(DateUtil.format(person.getBirthday()));
71 | birthdayField.setPromptText("dd.mm.yyyy");
72 | }
73 |
74 | /**
75 | * Returns true if the user clicked OK, false otherwise.
76 | *
77 | * @return
78 | */
79 | public boolean isOkClicked() {
80 | return okClicked;
81 | }
82 |
83 | /**
84 | * Called when the user clicks ok.
85 | */
86 | @FXML
87 | private void handleOk() {
88 | if (isInputValid()) {
89 | person.setFirstName(firstNameField.getText());
90 | person.setLastName(lastNameField.getText());
91 | person.setStreet(streetField.getText());
92 | person.setPostalCode(Integer.parseInt(postalCodeField.getText()));
93 | person.setCity(cityField.getText());
94 | person.setBirthday(DateUtil.parse(birthdayField.getText()));
95 |
96 | okClicked = true;
97 | dialogStage.close();
98 | }
99 | }
100 |
101 | /**
102 | * Called when the user clicks cancel.
103 | */
104 | @FXML
105 | private void handleCancel() {
106 | dialogStage.close();
107 | }
108 |
109 | /**
110 | * Validates the user input in the text fields.
111 | *
112 | * @return true if the input is valid
113 | */
114 | private boolean isInputValid() {
115 | String errorMessage = "";
116 |
117 | if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {
118 | errorMessage += "No valid first name!\n";
119 | }
120 | if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {
121 | errorMessage += "No valid last name!\n";
122 | }
123 | if (streetField.getText() == null || streetField.getText().length() == 0) {
124 | errorMessage += "No valid street!\n";
125 | }
126 |
127 | if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {
128 | errorMessage += "No valid postal code!\n";
129 | } else {
130 | // try to parse the postal code into an int.
131 | try {
132 | Integer.parseInt(postalCodeField.getText());
133 | } catch (NumberFormatException e) {
134 | errorMessage += "No valid postal code (must be an integer)!\n";
135 | }
136 | }
137 |
138 | if (cityField.getText() == null || cityField.getText().length() == 0) {
139 | errorMessage += "No valid city!\n";
140 | }
141 |
142 | if (birthdayField.getText() == null || birthdayField.getText().length() == 0) {
143 | errorMessage += "No valid birthday!\n";
144 | } else {
145 | if (!DateUtil.validDate(birthdayField.getText())) {
146 | errorMessage += "No valid birthday. Use the format dd.mm.yyyy!\n";
147 | }
148 | }
149 |
150 | if (errorMessage.length() == 0) {
151 | return true;
152 | } else {
153 | // Show the error message.
154 | Alert alert = new Alert(AlertType.ERROR);
155 | alert.initOwner(dialogStage);
156 | alert.setTitle("Invalid Fields");
157 | alert.setHeaderText("Please correct invalid fields");
158 | alert.setContentText(errorMessage);
159 |
160 | alert.showAndWait();
161 |
162 | return false;
163 | }
164 | }
165 | }
--------------------------------------------------------------------------------
/AddressApp-Part-7/src/ch/makery/address/view/PersonEditDialogController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.TextField;
7 | import javafx.scene.image.Image;
8 | import javafx.stage.Stage;
9 | import ch.makery.address.model.Person;
10 | import ch.makery.address.util.DateUtil;
11 |
12 | /**
13 | * Dialog to edit details of a person.
14 | *
15 | * @author Marco Jakob
16 | */
17 | public class PersonEditDialogController {
18 |
19 | @FXML
20 | private TextField firstNameField;
21 | @FXML
22 | private TextField lastNameField;
23 | @FXML
24 | private TextField streetField;
25 | @FXML
26 | private TextField postalCodeField;
27 | @FXML
28 | private TextField cityField;
29 | @FXML
30 | private TextField birthdayField;
31 |
32 |
33 | private Stage dialogStage;
34 | private Person person;
35 | private boolean okClicked = false;
36 |
37 | /**
38 | * Initializes the controller class. This method is automatically called
39 | * after the fxml file has been loaded.
40 | */
41 | @FXML
42 | private void initialize() {
43 | }
44 |
45 | /**
46 | * Sets the stage of this dialog.
47 | *
48 | * @param dialogStage
49 | */
50 | public void setDialogStage(Stage dialogStage) {
51 | this.dialogStage = dialogStage;
52 |
53 | // Set the dialog icon.
54 | this.dialogStage.getIcons().add(new Image("file:resources/images/edit.png"));
55 | }
56 |
57 | /**
58 | * Sets the person to be edited in the dialog.
59 | *
60 | * @param person
61 | */
62 | public void setPerson(Person person) {
63 | this.person = person;
64 |
65 | firstNameField.setText(person.getFirstName());
66 | lastNameField.setText(person.getLastName());
67 | streetField.setText(person.getStreet());
68 | postalCodeField.setText(Integer.toString(person.getPostalCode()));
69 | cityField.setText(person.getCity());
70 | birthdayField.setText(DateUtil.format(person.getBirthday()));
71 | birthdayField.setPromptText("dd.mm.yyyy");
72 | }
73 |
74 | /**
75 | * Returns true if the user clicked OK, false otherwise.
76 | *
77 | * @return
78 | */
79 | public boolean isOkClicked() {
80 | return okClicked;
81 | }
82 |
83 | /**
84 | * Called when the user clicks ok.
85 | */
86 | @FXML
87 | private void handleOk() {
88 | if (isInputValid()) {
89 | person.setFirstName(firstNameField.getText());
90 | person.setLastName(lastNameField.getText());
91 | person.setStreet(streetField.getText());
92 | person.setPostalCode(Integer.parseInt(postalCodeField.getText()));
93 | person.setCity(cityField.getText());
94 | person.setBirthday(DateUtil.parse(birthdayField.getText()));
95 |
96 | okClicked = true;
97 | dialogStage.close();
98 | }
99 | }
100 |
101 | /**
102 | * Called when the user clicks cancel.
103 | */
104 | @FXML
105 | private void handleCancel() {
106 | dialogStage.close();
107 | }
108 |
109 | /**
110 | * Validates the user input in the text fields.
111 | *
112 | * @return true if the input is valid
113 | */
114 | private boolean isInputValid() {
115 | String errorMessage = "";
116 |
117 | if (firstNameField.getText() == null || firstNameField.getText().length() == 0) {
118 | errorMessage += "No valid first name!\n";
119 | }
120 | if (lastNameField.getText() == null || lastNameField.getText().length() == 0) {
121 | errorMessage += "No valid last name!\n";
122 | }
123 | if (streetField.getText() == null || streetField.getText().length() == 0) {
124 | errorMessage += "No valid street!\n";
125 | }
126 |
127 | if (postalCodeField.getText() == null || postalCodeField.getText().length() == 0) {
128 | errorMessage += "No valid postal code!\n";
129 | } else {
130 | // try to parse the postal code into an int.
131 | try {
132 | Integer.parseInt(postalCodeField.getText());
133 | } catch (NumberFormatException e) {
134 | errorMessage += "No valid postal code (must be an integer)!\n";
135 | }
136 | }
137 |
138 | if (cityField.getText() == null || cityField.getText().length() == 0) {
139 | errorMessage += "No valid city!\n";
140 | }
141 |
142 | if (birthdayField.getText() == null || birthdayField.getText().length() == 0) {
143 | errorMessage += "No valid birthday!\n";
144 | } else {
145 | if (!DateUtil.validDate(birthdayField.getText())) {
146 | errorMessage += "No valid birthday. Use the format dd.mm.yyyy!\n";
147 | }
148 | }
149 |
150 | if (errorMessage.length() == 0) {
151 | return true;
152 | } else {
153 | // Show the error message.
154 | Alert alert = new Alert(AlertType.ERROR);
155 | alert.initOwner(dialogStage);
156 | alert.setTitle("Invalid Fields");
157 | alert.setHeaderText("Please correct invalid fields");
158 | alert.setContentText(errorMessage);
159 |
160 | alert.showAndWait();
161 |
162 | return false;
163 | }
164 | }
165 | }
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/MainApp.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address;
2 |
3 | import java.io.IOException;
4 |
5 | import javafx.application.Application;
6 | import javafx.collections.FXCollections;
7 | import javafx.collections.ObservableList;
8 | import javafx.fxml.FXMLLoader;
9 | import javafx.scene.Scene;
10 | import javafx.scene.image.Image;
11 | import javafx.scene.layout.AnchorPane;
12 | import javafx.scene.layout.BorderPane;
13 | import javafx.stage.Modality;
14 | import javafx.stage.Stage;
15 | import ch.makery.address.model.Person;
16 | import ch.makery.address.view.PersonEditDialogController;
17 | import ch.makery.address.view.PersonOverviewController;
18 |
19 | public class MainApp extends Application {
20 |
21 | private Stage primaryStage;
22 | private BorderPane rootLayout;
23 |
24 | /**
25 | * The data as an observable list of Persons.
26 | */
27 | private ObservableList personData = FXCollections.observableArrayList();
28 |
29 | /**
30 | * Constructor
31 | */
32 | public MainApp() {
33 | // Add some sample data
34 | personData.add(new Person("Hans", "Muster"));
35 | personData.add(new Person("Ruth", "Mueller"));
36 | personData.add(new Person("Heinz", "Kurz"));
37 | personData.add(new Person("Cornelia", "Meier"));
38 | personData.add(new Person("Werner", "Meyer"));
39 | personData.add(new Person("Lydia", "Kunz"));
40 | personData.add(new Person("Anna", "Best"));
41 | personData.add(new Person("Stefan", "Meier"));
42 | personData.add(new Person("Martin", "Mueller"));
43 | }
44 |
45 | /**
46 | * Returns the data as an observable list of Persons.
47 | * @return
48 | */
49 | public ObservableList getPersonData() {
50 | return personData;
51 | }
52 |
53 | @Override
54 | public void start(Stage primaryStage) {
55 | this.primaryStage = primaryStage;
56 | this.primaryStage.setTitle("AddressApp");
57 |
58 | // Set the application icon.
59 | this.primaryStage.getIcons().add(new Image("file:resources/images/address_book_32.png"));
60 |
61 | initRootLayout();
62 |
63 | showPersonOverview();
64 | }
65 |
66 | /**
67 | * Initializes the root layout.
68 | */
69 | public void initRootLayout() {
70 | try {
71 | // Load root layout from fxml file.
72 | FXMLLoader loader = new FXMLLoader();
73 | loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
74 | rootLayout = (BorderPane) loader.load();
75 |
76 | // Show the scene containing the root layout.
77 | Scene scene = new Scene(rootLayout);
78 | primaryStage.setScene(scene);
79 | primaryStage.show();
80 | } catch (IOException e) {
81 | e.printStackTrace();
82 | }
83 | }
84 |
85 | /**
86 | * Shows the person overview inside the root layout.
87 | */
88 | public void showPersonOverview() {
89 | try {
90 | // Load person overview.
91 | FXMLLoader loader = new FXMLLoader();
92 | loader.setLocation(MainApp.class.getResource("view/PersonOverview.fxml"));
93 | AnchorPane personOverview = (AnchorPane) loader.load();
94 |
95 | // Set person overview into the center of root layout.
96 | rootLayout.setCenter(personOverview);
97 |
98 | // Give the controller access to the main app.
99 | PersonOverviewController controller = loader.getController();
100 | controller.setMainApp(this);
101 |
102 | } catch (IOException e) {
103 | e.printStackTrace();
104 | }
105 | }
106 |
107 | /**
108 | * Opens a dialog to edit details for the specified person. If the user
109 | * clicks OK, the changes are saved into the provided person object and true
110 | * is returned.
111 | *
112 | * @param person the person object to be edited
113 | * @return true if the user clicked OK, false otherwise.
114 | */
115 | public boolean showPersonEditDialog(Person person) {
116 | try {
117 | // Load the fxml file and create a new stage for the popup dialog.
118 | FXMLLoader loader = new FXMLLoader();
119 | loader.setLocation(MainApp.class.getResource("view/PersonEditDialog.fxml"));
120 | AnchorPane page = (AnchorPane) loader.load();
121 |
122 | // Create the dialog Stage.
123 | Stage dialogStage = new Stage();
124 | dialogStage.setTitle("Edit Person");
125 | dialogStage.initModality(Modality.WINDOW_MODAL);
126 | dialogStage.initOwner(primaryStage);
127 | Scene scene = new Scene(page);
128 | dialogStage.setScene(scene);
129 |
130 | // Set the person into the controller.
131 | PersonEditDialogController controller = loader.getController();
132 | controller.setDialogStage(dialogStage);
133 | controller.setPerson(person);
134 |
135 | // Set the dialog icon.
136 | dialogStage.getIcons().add(new Image("file:resources/images/edit.png"));
137 |
138 | // Show the dialog and wait until the user closes it
139 | dialogStage.showAndWait();
140 |
141 | return controller.isOkClicked();
142 | } catch (IOException e) {
143 | e.printStackTrace();
144 | return false;
145 | }
146 | }
147 |
148 | /**
149 | * Returns the main stage.
150 | * @return
151 | */
152 | public Stage getPrimaryStage() {
153 | return primaryStage;
154 | }
155 |
156 | public static void main(String[] args) {
157 | launch(args);
158 | }
159 | }
--------------------------------------------------------------------------------
/AddressApp-Part-3/src/ch/makery/address/view/PersonOverviewController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.Label;
7 | import javafx.scene.control.TableColumn;
8 | import javafx.scene.control.TableView;
9 | import ch.makery.address.MainApp;
10 | import ch.makery.address.model.Person;
11 | import ch.makery.address.util.DateUtil;
12 |
13 | public class PersonOverviewController {
14 | @FXML
15 | private TableView personTable;
16 | @FXML
17 | private TableColumn firstNameColumn;
18 | @FXML
19 | private TableColumn lastNameColumn;
20 |
21 | @FXML
22 | private Label firstNameLabel;
23 | @FXML
24 | private Label lastNameLabel;
25 | @FXML
26 | private Label streetLabel;
27 | @FXML
28 | private Label postalCodeLabel;
29 | @FXML
30 | private Label cityLabel;
31 | @FXML
32 | private Label birthdayLabel;
33 |
34 | // Reference to the main application.
35 | private MainApp mainApp;
36 |
37 | /**
38 | * The constructor.
39 | * The constructor is called before the initialize() method.
40 | */
41 | public PersonOverviewController() {
42 | }
43 |
44 | /**
45 | * Initializes the controller class. This method is automatically called
46 | * after the fxml file has been loaded.
47 | */
48 | @FXML
49 | private void initialize() {
50 | // Initialize the person table with the two columns.
51 | firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
52 | lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
53 |
54 | // Clear person details.
55 | showPersonDetails(null);
56 |
57 | // Listen for selection changes and show the person details when changed.
58 | personTable.getSelectionModel().selectedItemProperty().addListener(
59 | (observable, oldValue, newValue) -> showPersonDetails(newValue));
60 | }
61 |
62 | /**
63 | * Is called by the main application to give a reference back to itself.
64 | *
65 | * @param mainApp
66 | */
67 | public void setMainApp(MainApp mainApp) {
68 | this.mainApp = mainApp;
69 |
70 | // Add observable list data to the table
71 | personTable.setItems(mainApp.getPersonData());
72 | }
73 |
74 | /**
75 | * Fills all text fields to show details about the person.
76 | * If the specified person is null, all text fields are cleared.
77 | *
78 | * @param person the person or null
79 | */
80 | private void showPersonDetails(Person person) {
81 | if (person != null) {
82 | // Fill the labels with info from the person object.
83 | firstNameLabel.setText(person.getFirstName());
84 | lastNameLabel.setText(person.getLastName());
85 | streetLabel.setText(person.getStreet());
86 | postalCodeLabel.setText(Integer.toString(person.getPostalCode()));
87 | cityLabel.setText(person.getCity());
88 | birthdayLabel.setText(DateUtil.format(person.getBirthday()));
89 | } else {
90 | // Person is null, remove all the text.
91 | firstNameLabel.setText("");
92 | lastNameLabel.setText("");
93 | streetLabel.setText("");
94 | postalCodeLabel.setText("");
95 | cityLabel.setText("");
96 | birthdayLabel.setText("");
97 | }
98 | }
99 |
100 | /**
101 | * Called when the user clicks on the delete button.
102 | */
103 | @FXML
104 | private void handleDeletePerson() {
105 | int selectedIndex = personTable.getSelectionModel().getSelectedIndex();
106 | if (selectedIndex >= 0) {
107 | personTable.getItems().remove(selectedIndex);
108 | } else {
109 | // Nothing selected.
110 | Alert alert = new Alert(AlertType.WARNING);
111 | alert.initOwner(mainApp.getPrimaryStage());
112 | alert.setTitle("No Selection");
113 | alert.setHeaderText("No Person Selected");
114 | alert.setContentText("Please select a person in the table.");
115 |
116 | alert.showAndWait();
117 | }
118 | }
119 |
120 | /**
121 | * Called when the user clicks the new button. Opens a dialog to edit
122 | * details for a new person.
123 | */
124 | @FXML
125 | private void handleNewPerson() {
126 | Person tempPerson = new Person();
127 | boolean okClicked = mainApp.showPersonEditDialog(tempPerson);
128 | if (okClicked) {
129 | mainApp.getPersonData().add(tempPerson);
130 | }
131 | }
132 |
133 | /**
134 | * Called when the user clicks the edit button. Opens a dialog to edit
135 | * details for the selected person.
136 | */
137 | @FXML
138 | private void handleEditPerson() {
139 | Person selectedPerson = personTable.getSelectionModel().getSelectedItem();
140 | if (selectedPerson != null) {
141 | boolean okClicked = mainApp.showPersonEditDialog(selectedPerson);
142 | if (okClicked) {
143 | showPersonDetails(selectedPerson);
144 | }
145 |
146 | } else {
147 | // Nothing selected.
148 | Alert alert = new Alert(AlertType.WARNING);
149 | alert.initOwner(mainApp.getPrimaryStage());
150 | alert.setTitle("No Selection");
151 | alert.setHeaderText("No Person Selected");
152 | alert.setContentText("Please select a person in the table.");
153 |
154 | alert.showAndWait();
155 | }
156 | }
157 | }
--------------------------------------------------------------------------------
/AddressApp-Part-4/src/ch/makery/address/view/PersonOverviewController.java:
--------------------------------------------------------------------------------
1 | package ch.makery.address.view;
2 |
3 | import javafx.fxml.FXML;
4 | import javafx.scene.control.Alert;
5 | import javafx.scene.control.Alert.AlertType;
6 | import javafx.scene.control.Label;
7 | import javafx.scene.control.TableColumn;
8 | import javafx.scene.control.TableView;
9 | import ch.makery.address.MainApp;
10 | import ch.makery.address.model.Person;
11 | import ch.makery.address.util.DateUtil;
12 |
13 | public class PersonOverviewController {
14 | @FXML
15 | private TableView personTable;
16 | @FXML
17 | private TableColumn firstNameColumn;
18 | @FXML
19 | private TableColumn lastNameColumn;
20 |
21 | @FXML
22 | private Label firstNameLabel;
23 | @FXML
24 | private Label lastNameLabel;
25 | @FXML
26 | private Label streetLabel;
27 | @FXML
28 | private Label postalCodeLabel;
29 | @FXML
30 | private Label cityLabel;
31 | @FXML
32 | private Label birthdayLabel;
33 |
34 | // Reference to the main application.
35 | private MainApp mainApp;
36 |
37 | /**
38 | * The constructor.
39 | * The constructor is called before the initialize() method.
40 | */
41 | public PersonOverviewController() {
42 | }
43 |
44 | /**
45 | * Initializes the controller class. This method is automatically called
46 | * after the fxml file has been loaded.
47 | */
48 | @FXML
49 | private void initialize() {
50 | // Initialize the person table with the two columns.
51 | firstNameColumn.setCellValueFactory(cellData -> cellData.getValue().firstNameProperty());
52 | lastNameColumn.setCellValueFactory(cellData -> cellData.getValue().lastNameProperty());
53 |
54 | // Clear person details.
55 | showPersonDetails(null);
56 |
57 | // Listen for selection changes and show the person details when changed.
58 | personTable.getSelectionModel().selectedItemProperty().addListener(
59 | (observable, oldValue, newValue) -> showPersonDetails(newValue));
60 | }
61 |
62 | /**
63 | * Is called by the main application to give a reference back to itself.
64 | *
65 | * @param mainApp
66 | */
67 | public void setMainApp(MainApp mainApp) {
68 | this.mainApp = mainApp;
69 |
70 | // Add observable list data to the table
71 | personTable.setItems(mainApp.getPersonData());
72 | }
73 |
74 | /**
75 | * Fills all text fields to show details about the person.
76 | * If the specified person is null, all text fields are cleared.
77 | *
78 | * @param person the person or null
79 | */
80 | private void showPersonDetails(Person person) {
81 | if (person != null) {
82 | // Fill the labels with info from the person object.
83 | firstNameLabel.setText(person.getFirstName());
84 | lastNameLabel.setText(person.getLastName());
85 | streetLabel.setText(person.getStreet());
86 | postalCodeLabel.setText(Integer.toString(person.getPostalCode()));
87 | cityLabel.setText(person.getCity());
88 | birthdayLabel.setText(DateUtil.format(person.getBirthday()));
89 | } else {
90 | // Person is null, remove all the text.
91 | firstNameLabel.setText("");
92 | lastNameLabel.setText("");
93 | streetLabel.setText("");
94 | postalCodeLabel.setText("");
95 | cityLabel.setText("");
96 | birthdayLabel.setText("");
97 | }
98 | }
99 |
100 | /**
101 | * Called when the user clicks on the delete button.
102 | */
103 | @FXML
104 | private void handleDeletePerson() {
105 | int selectedIndex = personTable.getSelectionModel().getSelectedIndex();
106 | if (selectedIndex >= 0) {
107 | personTable.getItems().remove(selectedIndex);
108 | } else {
109 | // Nothing selected.
110 | Alert alert = new Alert(AlertType.WARNING);
111 | alert.initOwner(mainApp.getPrimaryStage());
112 | alert.setTitle("No Selection");
113 | alert.setHeaderText("No Person Selected");
114 | alert.setContentText("Please select a person in the table.");
115 |
116 | alert.showAndWait();
117 | }
118 | }
119 |
120 | /**
121 | * Called when the user clicks the new button. Opens a dialog to edit
122 | * details for a new person.
123 | */
124 | @FXML
125 | private void handleNewPerson() {
126 | Person tempPerson = new Person();
127 | boolean okClicked = mainApp.showPersonEditDialog(tempPerson);
128 | if (okClicked) {
129 | mainApp.getPersonData().add(tempPerson);
130 | }
131 | }
132 |
133 | /**
134 | * Called when the user clicks the edit button. Opens a dialog to edit
135 | * details for the selected person.
136 | */
137 | @FXML
138 | private void handleEditPerson() {
139 | Person selectedPerson = personTable.getSelectionModel().getSelectedItem();
140 | if (selectedPerson != null) {
141 | boolean okClicked = mainApp.showPersonEditDialog(selectedPerson);
142 | if (okClicked) {
143 | showPersonDetails(selectedPerson);
144 | }
145 |
146 | } else {
147 | // Nothing selected.
148 | Alert alert = new Alert(AlertType.WARNING);
149 | alert.initOwner(mainApp.getPrimaryStage());
150 | alert.setTitle("No Selection");
151 | alert.setHeaderText("No Person Selected");
152 | alert.setContentText("Please select a person in the table.");
153 |
154 | alert.showAndWait();
155 | }
156 | }
157 | }
--------------------------------------------------------------------------------