Skip to content

Commit 3ef055e

Browse files
committed
Dynamic style, add certificate view, handle IOException on Desktop open, working on network config (proxy, bandwidth limit)
1 parent ad60f22 commit 3ef055e

File tree

13 files changed

+246
-38
lines changed

13 files changed

+246
-38
lines changed

src/main/kotlin/com/valaphee/blit/AboutView.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616

1717
package com.valaphee.blit
1818

19+
import com.valaphee.blit.data.config.Config
1920
import javafx.geometry.Pos
2021
import javafx.scene.image.Image
2122
import javafx.scene.text.TextAlignment
22-
import jfxtras.styles.jmetro.JMetro
2323
import jfxtras.styles.jmetro.JMetroStyleClass
24-
import jfxtras.styles.jmetro.Style
2524
import tornadofx.View
2625
import tornadofx.hbox
2726
import tornadofx.imageview
@@ -31,8 +30,10 @@ import tornadofx.label
3130
* @author Kevin Ludwig
3231
*/
3332
class AboutView : View("About Blit") {
33+
private val _config by di<Config>()
34+
3435
override val root = hbox {
35-
JMetro(this, Style.DARK)
36+
_config.theme.apply(this)
3637
styleClass.add(JMetroStyleClass.BACKGROUND)
3738

3839
prefWidth = 300.0
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2021, Valaphee.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.valaphee.blit
18+
19+
import com.valaphee.blit.data.config.Config
20+
import com.valaphee.blit.data.locale.Locale
21+
import javafx.stage.Stage
22+
import jfxtras.styles.jmetro.JMetroStyleClass
23+
import tornadofx.View
24+
import tornadofx.action
25+
import tornadofx.button
26+
import tornadofx.buttonbar
27+
import tornadofx.form
28+
import tornadofx.readonlyColumn
29+
import tornadofx.smartResize
30+
import tornadofx.tableview
31+
import tornadofx.toObservable
32+
import java.security.cert.X509Certificate
33+
34+
/**
35+
* @author Kevin Ludwig
36+
*/
37+
class CertificateView(
38+
private val chain: Array<out X509Certificate>,
39+
private val valid: Boolean
40+
) : View("Certificate${if (!valid) " (Invalid)" else ""}") {
41+
private val locale by di<Locale>()
42+
private val _config by di<Config>()
43+
44+
override val root = form {
45+
_config.theme.apply(this)
46+
styleClass.add(JMetroStyleClass.BACKGROUND)
47+
48+
prefWidth = 500.0
49+
50+
val certificate = chain.first()
51+
tableview(listOf(
52+
"Version" to "V${certificate.version}",
53+
"Serial number" to certificate.serialNumber.toString(16),
54+
"Signature algorithm" to certificate.sigAlgName,
55+
"Issuer" to certificate.issuerDN,
56+
"Valid from" to certificate.notBefore,
57+
"Valid to" to certificate.notAfter,
58+
"Subject" to certificate.subjectDN
59+
).toObservable()) {
60+
readonlyColumn("Field", Pair<String, Any>::first)
61+
readonlyColumn("Value", Pair<String, Any>::second)
62+
smartResize()
63+
64+
setSortPolicy { false }
65+
}
66+
buttonbar { button(locale["rename.ok.text"]) { action { (scene.window as Stage).close() } } }
67+
}
68+
}

src/main/kotlin/com/valaphee/blit/ErrorView.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,14 @@
1616

1717
package com.valaphee.blit
1818

19+
import com.valaphee.blit.data.config.Config
1920
import com.valaphee.blit.data.locale.Locale
2021
import javafx.stage.Stage
21-
import jfxtras.styles.jmetro.JMetro
2222
import jfxtras.styles.jmetro.JMetroStyleClass
23-
import jfxtras.styles.jmetro.Style
2423
import tornadofx.View
2524
import tornadofx.action
2625
import tornadofx.button
2726
import tornadofx.buttonbar
28-
import tornadofx.field
29-
import tornadofx.fieldset
3027
import tornadofx.form
3128
import tornadofx.label
3229

@@ -38,14 +35,15 @@ class ErrorView(
3835
errorMessage: String,
3936
) : View(error) {
4037
private val locale by di<Locale>()
38+
private val _config by di<Config>()
4139

4240
override val root = form {
43-
JMetro(this, Style.DARK)
41+
_config.theme.apply(this)
4442
styleClass.add(JMetroStyleClass.BACKGROUND)
4543

4644
prefWidth = 300.0
4745

48-
fieldset { field { label(errorMessage) } }
46+
label(errorMessage)
4947
buttonbar { button(locale["rename.ok.text"]) { action { (scene.window as Stage).close() } } }
5048
}
5149
}

src/main/kotlin/com/valaphee/blit/MainView.kt

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.valaphee.blit
1919
import com.valaphee.blit.data.config.Config
2020
import com.valaphee.blit.data.config.ConfigView
2121
import com.valaphee.blit.data.config.ConfigViewGeneral
22+
import com.valaphee.blit.data.config.ConfigViewNetwork
2223
import com.valaphee.blit.data.config.ConfigViewSources
2324
import com.valaphee.blit.data.locale.Locale
2425
import com.valaphee.blit.data.manifest.IconManifest
@@ -28,6 +29,7 @@ import com.valaphee.blit.source.SourceConfig
2829
import javafx.beans.property.SimpleObjectProperty
2930
import javafx.beans.property.SimpleStringProperty
3031
import javafx.scene.control.ContextMenu
32+
import javafx.scene.control.Label
3133
import javafx.scene.control.SelectionMode
3234
import javafx.scene.control.TableColumnBase
3335
import javafx.scene.control.TreeItem
@@ -41,9 +43,7 @@ import javafx.scene.input.TransferMode
4143
import javafx.scene.layout.Priority
4244
import javafx.scene.layout.VBox
4345
import javafx.stage.Stage
44-
import jfxtras.styles.jmetro.JMetro
4546
import jfxtras.styles.jmetro.JMetroStyleClass
46-
import jfxtras.styles.jmetro.Style
4747
import org.bridj.cpp.com.COMRuntime
4848
import org.bridj.cpp.com.shell.ITaskbarList3
4949
import org.controlsfx.control.BreadCrumbBar
@@ -77,6 +77,7 @@ import java.awt.Desktop
7777
import java.io.File
7878
import java.io.FileInputStream
7979
import java.io.FileOutputStream
80+
import java.io.IOException
8081
import java.text.DateFormat
8182
import java.util.concurrent.CompletableFuture
8283

@@ -105,7 +106,7 @@ class MainView : View("Blit") {
105106
private val dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale.toJavaLocale())
106107

107108
override val root = vbox {
108-
JMetro(this, Style.DARK)
109+
_config.theme.apply(this)
109110
styleClass.add(JMetroStyleClass.BACKGROUND)
110111

111112
prefWidth = 1000.0
@@ -129,6 +130,14 @@ class MainView : View("Blit") {
129130
}
130131
}
131132
}
133+
item(locale["main.menu.file.network.name"]) {
134+
action {
135+
find<ConfigView> {
136+
select<ConfigViewNetwork>()
137+
openModal()
138+
}
139+
}
140+
}
132141
separator()
133142
item(locale["main.menu.file.exit.name"]) { action { (scene.window as Stage).close() } }
134143
}
@@ -234,6 +243,8 @@ class MainView : View("Blit") {
234243
isShowRoot = false
235244
selectionModel.selectionMode = SelectionMode.MULTIPLE
236245

246+
placeholder = Label("")
247+
237248
column(locale["main.tree.column.name.title"], Entry<T>::self) {
238249
tableColumnBaseSetWidth(this, 250.0)
239250
cellFormat {
@@ -291,10 +302,19 @@ class MainView : View("Blit") {
291302

292303
selectionModel.selectedItems.onChange {
293304
contextMenu = ContextMenu().apply {
294-
item(locale["main.tree.menu.open.name"]) { action { it.list.firstOrNull { it.value.directory }?.value?.let { navigateRelative(it.toString()) } ?: it.list.forEach(::open) } }
295-
separator()
296-
item(locale["main.tree.menu.rename.name"]) { action { it.list.forEach(::rename) } }
297-
item(locale["main.tree.menu.delete.name"]) { action { it.list.forEach(::delete) } }
305+
if (it.list.isEmpty()) {
306+
item(locale["main.tree.menu.parent.name"]) { action { navigateRelative("..") } }
307+
separator()
308+
item(locale["main.tree.menu.new_directory.name"]) { action {} }
309+
item(locale["main.tree.menu.new_file.name"]) { action {} }
310+
separator()
311+
item(locale["main.tree.menu.refresh.name"]) { action { populate(root) } }
312+
} else {
313+
item(locale["main.tree.menu.open.name"]) { action { it.list.firstOrNull { it.value.directory }?.value?.let { navigateRelative(it.toString()) } ?: it.list.forEach(::open) } }
314+
separator()
315+
item(locale["main.tree.menu.rename.name"]) { action { it.list.forEach(::rename) } }
316+
item(locale["main.tree.menu.delete.name"]) { action { it.list.forEach(::delete) } }
317+
}
298318
}
299319
}
300320

@@ -328,15 +348,18 @@ class MainView : View("Blit") {
328348
KeyCode.F5 -> populate(root)
329349
}
330350
}
331-
setOnMousePressed {
332-
if (it.isPrimaryButtonDown && it.clickCount == 2) selectionModel.selectedItem?.let { if (!it.value.directory) open(it) }
333-
}
351+
setOnMousePressed { if (it.isPrimaryButtonDown && it.clickCount == 2) selectionModel.selectedItem?.let { if (!it.value.directory) open(it) } }
334352
}
335353

336354
private fun open(item: TreeItem<Entry<T>>) {
337355
if (Desktop.isDesktopSupported()) {
338356
val entry = item.value
339-
activity.launch(locale["main.tree.task.download.name", entry]) { Desktop.getDesktop().open(File(_config.temporaryPath, entry.name).apply { FileOutputStream(this).use { entry.transferTo(it) } }) } // TODO: Desktop.open throws IOException (No application is associated with the specific file for this operation.)
357+
activity.launch(locale["main.tree.task.download.name", entry]) {
358+
val file = File(_config.temporaryPath, entry.name).apply { FileOutputStream(this).use { entry.transferTo(it) } }
359+
try {
360+
Desktop.getDesktop().open(file)
361+
} catch (_: IOException) {}
362+
}
340363
}
341364
}
342365

src/main/kotlin/com/valaphee/blit/RenameView.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@
1616

1717
package com.valaphee.blit
1818

19+
import com.valaphee.blit.data.config.Config
1920
import com.valaphee.blit.data.locale.Locale
2021
import javafx.beans.property.SimpleStringProperty
2122
import javafx.stage.Stage
22-
import jfxtras.styles.jmetro.JMetro
2323
import jfxtras.styles.jmetro.JMetroStyleClass
24-
import jfxtras.styles.jmetro.Style
2524
import tornadofx.View
2625
import tornadofx.action
2726
import tornadofx.button
@@ -40,11 +39,12 @@ class RenameView(
4039
action: (String) -> Unit
4140
) : View("Rename $name") {
4241
private val locale by di<Locale>()
42+
private val _config by di<Config>()
4343

4444
private val name = SimpleStringProperty(name)
4545

4646
override val root = form {
47-
JMetro(this, Style.DARK)
47+
_config.theme.apply(this)
4848
styleClass.add(JMetroStyleClass.BACKGROUND)
4949

5050
prefWidth = 300.0

src/main/kotlin/com/valaphee/blit/data/config/Config.kt

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,25 @@ package com.valaphee.blit.data.config
1818

1919
import com.fasterxml.jackson.annotation.JsonIgnore
2020
import com.fasterxml.jackson.annotation.JsonValue
21+
import com.fasterxml.jackson.databind.ObjectMapper
2122
import com.google.inject.Inject
2223
import com.google.inject.Singleton
2324
import com.valaphee.blit.data.Data
2425
import com.valaphee.blit.data.DataType
2526
import com.valaphee.blit.source.SourceConfig
27+
import com.valaphee.blit.source.local.LocalSourceConfig
2628
import javafx.beans.property.SimpleListProperty
2729
import javafx.beans.property.SimpleObjectProperty
2830
import javafx.beans.property.SimpleStringProperty
2931
import javafx.collections.ObservableList
32+
import javafx.scene.Parent
33+
import jfxtras.styles.jmetro.JMetro
34+
import jfxtras.styles.jmetro.Style
3035
import tornadofx.ItemViewModel
3136
import tornadofx.asObservable
3237
import tornadofx.getValue
3338
import tornadofx.setValue
39+
import java.io.File
3440
import java.text.StringCharacterIterator
3541
import kotlin.math.abs
3642

@@ -40,16 +46,26 @@ import kotlin.math.abs
4046
@Singleton
4147
@DataType("config")
4248
class Config(
43-
locale: String,
44-
dataSizeUnit: DataSizeUnit,
45-
temporaryPath: String,
46-
sources: List<SourceConfig>
49+
theme: Theme = Theme.Light,
50+
locale: String = "en_US",
51+
dataSizeUnit: DataSizeUnit = DataSizeUnit.IEC,
52+
temporaryPath: String = System.getProperty("java.tmpdir"),
53+
sources: List<SourceConfig> = listOf(LocalSourceConfig("local"))
4754
) : Data {
55+
enum class Theme(
56+
@get:JsonValue val key: String,
57+
val apply: (Parent) -> Unit
58+
) {
59+
SystemDefault("system_default", { JMetro(it, Style.DARK) }),
60+
Light("light", { JMetro(it, Style.LIGHT) }),
61+
Dark("dark", { JMetro(it, Style.DARK) })
62+
}
63+
4864
enum class DataSizeUnit(
4965
@get:JsonValue val key: String,
5066
val format: (Long) -> String
5167
) {
52-
BYTES("bytes", { it.toString() }),
68+
Bytes("bytes", { it.toString() }),
5369
IEC("iec", {
5470
val sizeAbs = if (it == Long.MIN_VALUE) Long.MAX_VALUE else abs(it)
5571
if (sizeAbs < 1024) "$it B" else {
@@ -78,6 +94,9 @@ class Config(
7894
})
7995
}
8096

97+
@get:JsonIgnore internal val themeProperty = SimpleObjectProperty(theme)
98+
var theme: Theme by themeProperty
99+
81100
@get:JsonIgnore internal val localeProperty = SimpleStringProperty(locale)
82101
var locale: String by localeProperty
83102

@@ -94,9 +113,16 @@ class Config(
94113
class Model @Inject constructor(
95114
config: Config
96115
) : ItemViewModel<Config>(config) {
116+
private val objectMapper by di<ObjectMapper>()
117+
118+
val theme = bind(Config::themeProperty)
97119
val locale = bind(Config::localeProperty)
98120
val dataSizeUnit = bind(Config::dataSizeUnitProperty)
99121
val temporaryPath = bind(Config::temporaryPathProperty)
100122
val sources = bind(Config::sourcesProperty)
123+
124+
override fun onCommit() {
125+
objectMapper.writeValue(File(File("data").also(File::mkdir), "config.json"), Config(theme.value, locale.value, dataSizeUnit.value, temporaryPath.value, sources))
126+
}
101127
}
102128
}

src/main/kotlin/com/valaphee/blit/data/config/ConfigView.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ import javafx.scene.control.Tab
2121
import javafx.scene.control.TabPane
2222
import javafx.scene.layout.Priority
2323
import javafx.stage.Stage
24-
import jfxtras.styles.jmetro.JMetro
2524
import jfxtras.styles.jmetro.JMetroStyleClass
26-
import jfxtras.styles.jmetro.Style
2725
import tornadofx.Component
2826
import tornadofx.Fragment
2927
import tornadofx.View
@@ -43,12 +41,13 @@ import kotlin.reflect.KClass
4341
*/
4442
class ConfigView : View("Configure Blit") {
4543
private val locale by di<Locale>()
44+
private val _config by di<Config>()
4645
private val configModel by di<Config.Model>()
4746

4847
private var tabs = mutableMapOf<KClass<out Component>, Tab>()
4948

5049
override val root = vbox {
51-
JMetro(this, Style.DARK)
50+
_config.theme.apply(this)
5251
styleClass.add(JMetroStyleClass.BACKGROUND)
5352

5453
prefWidth = 800.0
@@ -60,6 +59,7 @@ class ConfigView : View("Configure Blit") {
6059

6160
this@ConfigView.tabs[ConfigViewGeneral::class] = tab(ConfigViewGeneral::class)
6261
this@ConfigView.tabs[ConfigViewSources::class] = tab(ConfigViewSources::class)
62+
this@ConfigView.tabs[ConfigViewNetwork::class] = tab(ConfigViewNetwork::class)
6363
}
6464
buttonbar {
6565
button(locale["config.ok.text"]) {

0 commit comments

Comments
 (0)