@@ -31,6 +31,7 @@ import javafx.scene.control.ContextMenu
3131import javafx.scene.control.Label
3232import javafx.scene.control.SelectionMode
3333import javafx.scene.control.TableColumnBase
34+ import javafx.scene.control.TextField
3435import javafx.scene.control.TreeItem
3536import javafx.scene.control.TreeTableRow
3637import javafx.scene.control.TreeTableView
@@ -62,14 +63,14 @@ import tornadofx.menu
6263import tornadofx.menubar
6364import tornadofx.onChange
6465import tornadofx.paddingTop
65- import tornadofx.pane
6666import tornadofx.populateTree
6767import tornadofx.progressbar
6868import tornadofx.runLater
6969import tornadofx.separator
7070import tornadofx.setContent
7171import tornadofx.splitpane
7272import tornadofx.style
73+ import tornadofx.useMaxSize
7374import tornadofx.vbox
7475import tornadofx.vgrow
7576import java.awt.Desktop
@@ -139,10 +140,12 @@ class MainView : View("Blit") {
139140 }
140141
141142 hbox {
142- pane { hgrow = Priority .ALWAYS }
143+ progressbar(activity.progress) {
144+ hgrow = Priority .ALWAYS
145+ useMaxSize = true
146+ }
143147 button(" ..." ) { action { find<ActivityView >().openWindow() } }
144148 }
145- progressbar(activity.progress)
146149 }
147150
148151 inner class Pane <T : Entry <T >> : VBox () {
@@ -181,7 +184,7 @@ class MainView : View("Blit") {
181184
182185 tree.rootProperty().onChange {
183186 it?.let {
184- val path = it.value.toString()
187+ val path = it.value.path
185188 selectedCrumb = if (path == " /" ) BreadCrumbBar .buildTreeModel(" /" ) else BreadCrumbBar .buildTreeModel(* path.toCanonicalPath().toTypedArray().apply { if (this .getOrNull(0 )?.isEmpty() == true ) this [0 ] = " /" })
186189 }
187190 }
@@ -234,24 +237,19 @@ class MainView : View("Blit") {
234237 vgrow = Priority .ALWAYS
235238 isShowRoot = false
236239 selectionModel.selectionMode = SelectionMode .MULTIPLE
237- /* isEditable = true*/
240+ isEditable = true
238241 placeholder = Label (" " )
239242
240243 column(locale[" main.tree.column.name.title" ], Entry <T >::self) {
241244 tableColumnBaseSetWidth(this , 250.0 )
242245 setCellFactory {
243246 object : TextFieldTreeTableCell <Entry <T >, Entry <T >>() {
244- private val defaultStyle = style
245- private val defaultStyleClass = listOf (* styleClass.toTypedArray())
246-
247247 override fun updateItem (item : Entry <T >? , empty : Boolean ) {
248248 super .updateItem(item, empty)
249249
250250 if (item == null || empty) {
251251 text = null
252252 graphic = null
253- style = defaultStyle
254- styleClass.setAll(defaultStyleClass)
255253 } else {
256254 val name = item.name
257255 text = name
@@ -261,6 +259,33 @@ class MainView : View("Blit") {
261259 }
262260 }
263261 }
262+
263+ override fun startEdit () {
264+ val textFieldNull = textFieldTreeTableCellTextField[this ] == null
265+
266+ super .startEdit()
267+
268+ if (textFieldNull) {
269+ val textField = (textFieldTreeTableCellTextField[this ] as TextField )
270+ textField.setOnAction {
271+ activity.launch(locale[" main.tree.task.rename.name" , item, textField.text]) { item.rename(" ${item.path.substringBeforeLast(' /' , " " )} /${textField.text} " ) }
272+
273+ cancelEdit()
274+ it.consume()
275+ }
276+ }
277+ }
278+
279+ override fun cancelEdit () {
280+ super .cancelEdit()
281+
282+ val name = item.name
283+ text = name
284+ graphic = if (item.directory) ImageView ((iconManifest.folderIcons.firstOrNull { it.folderNames.contains(name) } ? : iconManifest.defaultFolderIcon).image) else run {
285+ val extension = name.substringAfterLast(' .' , " " )
286+ ImageView ((iconManifest.fileIcons.firstOrNull { it.fileExtensions.contains(extension) || it.fileNames.contains(name) } ? : iconManifest.defaultFileIcon).image)
287+ }
288+ }
264289 }
265290 }
266291 setComparator { a, b -> a.name.compareTo(b.name) }
@@ -279,7 +304,6 @@ class MainView : View("Blit") {
279304 TreeTableRow <Entry <T >>().apply {
280305 setOnMouseClicked {
281306 if (isEmpty) selectionModel.clearSelection()
282-
283307 it.consume()
284308 }
285309 setOnDragDetected {
@@ -292,12 +316,10 @@ class MainView : View("Blit") {
292316 dragEntries[id] = selectionModel.selectedItems.map { it.value }
293317 }
294318 }
295-
296319 it.consume()
297320 }
298321 setOnDragOver {
299322 if (source != null && (it.gestureSource != this && it.dragboard.hasFiles() || it.dragboard.hasContent(dragEntriesFormat))) it.acceptTransferModes(* TransferMode .COPY_OR_MOVE )
300-
301323 it.consume()
302324 }
303325 setOnDragDropped {
@@ -326,7 +348,6 @@ class MainView : View("Blit") {
326348 }
327349 } else TODO ()
328350 }
329-
330351 it.consume()
331352 }
332353 }
@@ -342,45 +363,65 @@ class MainView : View("Blit") {
342363 separator()
343364 item(locale[" main.tree.menu.refresh.name" ]) { action { populate(root) } }
344365 } else {
345- item(locale[" main.tree.menu.open.name" ]) { action { it.list.firstOrNull { it.value.directory }?.value?.let { navigateRelative(it.toString() ) } ? : it.list.forEach(::open) } }
366+ item(locale[" main.tree.menu.open.name" ]) { action { it.list.firstOrNull { it.value.directory }?.value?.let { navigateRelative(it.path ) } ? : it.list.forEach(::open) } }
346367 separator()
347- item(locale[" main.tree.menu.rename.name" ]) { action { it.list.forEach(::rename) } }
368+ item(locale[" main.tree.menu.rename.name" ]) { action {} }
348369 item(locale[" main.tree.menu.delete.name" ]) { action { it.list.forEach(::delete) } }
349370 }
350371 }
351372 }
352373
353374 setOnKeyPressed {
354375 when (it.code) {
355- KeyCode .ENTER -> selectionModel.selectedItems.firstOrNull { it.value.directory }?.value?.let { navigateRelative(it.toString()) } ? : selectionModel.selectedItems.forEach(::open)
356- KeyCode .BACK_SPACE -> navigateRelative(" .." )
357- KeyCode .C -> if (it.isControlDown) Clipboard .getSystemClipboard().setContent {
358- activity.runBlocking(locale[" main.tree.task.download.name" ]) {
359- suspend fun flatten (entry : Entry <T >, path : String? = null): List <File > = if (entry.directory) {
360- File (_config .temporaryPath, entry.name).mkdir()
361- entry.list().flatMap { flatten(it, " ${path?.let { " $path /" } ? : " " }${entry.name} " ) }
362- } else listOf (File (_config .temporaryPath, " ${path?.let { " $path /" } ? : " " }${entry.name} " ).apply { FileOutputStream (this ).use { entry.transferTo(it) } })
363-
364- putFiles(selectionModel.selectedItems.flatMap { flatten(it.value) })
365-
366- it.consume()
376+ KeyCode .ENTER -> {
377+ selectionModel.selectedItems.firstOrNull { it.value.directory }?.value?.let { navigateRelative(it.path) } ? : selectionModel.selectedItems.forEach(::open)
378+ it.consume()
379+ }
380+ KeyCode .BACK_SPACE -> {
381+ navigateRelative(" .." )
382+ it.consume()
383+ }
384+ KeyCode .C -> if (it.isControlDown) {
385+ Clipboard .getSystemClipboard().setContent {
386+ activity.runBlocking(locale[" main.tree.task.download.name" ]) {
387+ suspend fun flatten (entry : Entry <T >, path : String? = null): List <File > = if (entry.directory) {
388+ File (_config .temporaryPath, entry.name).mkdir()
389+ entry.list().flatMap { flatten(it, " ${path?.let { " $path /" } ? : " " }${entry.name} " ) }
390+ } else listOf (File (_config .temporaryPath, " ${path?.let { " $path /" } ? : " " }${entry.name} " ).apply { FileOutputStream (this ).use { entry.transferTo(it) } })
391+
392+ putFiles(selectionModel.selectedItems.flatMap { flatten(it.value) })
393+ it.consume()
394+ }
367395 }
368396 }
369- KeyCode .D -> if (it.isControlDown) selectionModel.selectedItems.forEach(::delete)
370- KeyCode .V -> if (it.isControlDown) with (Clipboard .getSystemClipboard()) {
371- if (hasFiles()) {
372- val item = selectionModel.selectedItem ? : root
373- val entry = item.value
374- if (! entry.directory) TODO ()
375- files.forEach { file -> activity.launch(locale[" main.tree.task.upload.name" , file.name]) { FileInputStream (file).use { entry.transferFrom(file.name, it, file.length()) } } }
397+ KeyCode .D -> if (it.isControlDown) {
398+ selectionModel.selectedItems.forEach(::delete)
399+ it.consume()
400+ }
401+ KeyCode .V -> if (it.isControlDown) {
402+ with (Clipboard .getSystemClipboard()) {
403+ if (hasFiles()) {
404+ val item = selectionModel.selectedItem ? : root
405+ val entry = item.value
406+ if (! entry.directory) TODO ()
407+ files.forEach { file -> activity.launch(locale[" main.tree.task.upload.name" , file.name]) { FileInputStream (file).use { entry.transferFrom(file.name, it, file.length()) } } }
408+ }
376409 }
410+ it.consume()
411+ }
412+ KeyCode .DELETE -> {
413+ selectionModel.selectedItems.forEach(::delete)
414+ it.consume()
377415 }
378- KeyCode .DELETE -> selectionModel.selectedItems.forEach(::delete)
379- KeyCode .F2 -> selectionModel.selectedItems.forEach(::rename)
380416 KeyCode .F5 -> populate(root)
381417 }
382418 }
383- setOnMousePressed { if (it.isPrimaryButtonDown && it.clickCount == 2 ) selectionModel.selectedItem?.let { if (! it.value.directory) open(it) } }
419+ setOnMousePressed {
420+ if (it.isPrimaryButtonDown && it.clickCount == 2 ) {
421+ selectionModel.selectedItem?.let { if (! it.value.directory) open(it) }
422+ it.consume()
423+ }
424+ }
384425 }
385426
386427 private fun open (item : TreeItem <Entry <T >>) {
@@ -396,11 +437,6 @@ class MainView : View("Blit") {
396437 }
397438 }
398439
399- private fun rename (item : TreeItem <Entry <T >>) {
400- val entry = item.value
401- RenameView (entry.toString()) { activity.launch(locale[" main.tree.task.rename.name" , entry, it]) { entry.rename(it) } }.openModal(resizable = false )
402- }
403-
404440 private fun delete (item : TreeItem <Entry <T >>) {
405441 val entry = item.value
406442 activity.launch(locale[" main.tree.task.delete.name" , entry.name]) { entry.delete() }
@@ -428,6 +464,7 @@ class MainView : View("Blit") {
428464 companion object {
429465 private val windowsRootPath = " ^[a-zA-Z]:[\\\\ /].*\$ " .toRegex()
430466 internal val tableColumnBaseSetWidth = TableColumnBase ::class .java.getDeclaredMethod(" setWidth" , Double ::class .java).apply { isAccessible = true }
467+ private val textFieldTreeTableCellTextField = TextFieldTreeTableCell ::class .java.getDeclaredField(" textField" ).apply { isAccessible = true }
431468 private val dragEntriesFormat = DataFormat (" application/blit-entry-id" )
432469
433470 internal fun String.toCanonicalPath (): List <String > {
0 commit comments