Skip to content

Commit

Permalink
Move common content update logic out of the demo
Browse files Browse the repository at this point in the history
For #8
  • Loading branch information
kirill-grouchnikov committed Jan 12, 2022
1 parent 9fff4cc commit f471f81
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 107 deletions.
Expand Up @@ -20,7 +20,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.painter.Painter
Expand All @@ -32,8 +31,6 @@ import androidx.compose.ui.text.resolveDefaults
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.pushingpixels.aurora.common.AuroraInternalApi
import org.pushingpixels.aurora.common.withAlpha
Expand All @@ -48,7 +45,7 @@ import org.pushingpixels.aurora.theming.*
@OptIn(AuroraInternalApi::class)
@Composable
fun AuroraBreadcrumbBar(
contentModel: SnapshotStateList<Command>,
contentModel: List<Command>,
presentationModel: BreadcrumbBarPresentationModel = BreadcrumbBarPresentationModel(),
modifier: Modifier
) {
Expand Down
Expand Up @@ -15,7 +15,12 @@
*/
package org.pushingpixels.aurora.component.model

import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.graphics.painter.Painter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.pushingpixels.aurora.theming.BackgroundAppearanceStrategy
import org.pushingpixels.aurora.theming.IconFilterStrategy
import java.io.InputStream
Expand Down Expand Up @@ -59,6 +64,83 @@ interface BreadcrumbBarContentProvider<T> {
suspend fun getLeafContent(leaf: T): InputStream? = null
}

suspend fun <T> BreadcrumbBarContentProvider<T>.getPathCommand(
scope: CoroutineScope,
commands: SnapshotStateList<Command>,
item: T?,
onItemSelected: (T) -> Unit,
level: Int
): Command {
// These will be displayed in the dropdown
val pathChoices = this.getPathChoices(item)

return Command(
text = this.getDisplayText(item),
icon = this.getIcon(item),
action = {
// This is called when the path item is clicked
while (commands.size > level) {
commands.removeLast()
}
scope.launch {
onItemSelected.invoke(item!!)
}
},
secondaryContentModel = if (pathChoices.isNotEmpty()) CommandMenuContentModel(
group = CommandGroup(title = null,
commands = pathChoices.map { pathChoice ->
Command(text = this.getDisplayText(pathChoice),
icon = this.getIcon(pathChoice),
action = {
// This is called when a dropdown item is clicked
while (commands.size > level) {
commands.removeLast()
}
scope.launch {
commands.add(
getPathCommand(
scope = scope,
commands = commands,
item = pathChoice,
onItemSelected = onItemSelected,
level = level + 1
)
)
onItemSelected.invoke(pathChoice)
}
})
}
)
) else null
)
}

@Composable
fun <T> BreadcrumbBarContentModel(
contentProvider: BreadcrumbBarContentProvider<T>,
onItemSelected: (T) -> Unit
): SnapshotStateList<Command> {
val commands = remember { mutableStateListOf<Command>() }
val scope = rememberCoroutineScope()

LaunchedEffect(null) {
coroutineScope {
// Root content for the breadcrumb bar
commands.add(
contentProvider.getPathCommand(
scope = scope,
commands = commands,
item = null,
onItemSelected = onItemSelected,
level = 1
)
)
}
}

return commands
}

data class BreadcrumbBarPresentationModel(
val presentationState: CommandButtonPresentationState = CommandButtonPresentationState.Medium,
val backgroundAppearanceStrategy: BackgroundAppearanceStrategy = BackgroundAppearanceStrategy.Flat,
Expand Down
Expand Up @@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.WindowPosition
import androidx.compose.ui.window.rememberWindowState
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.pushingpixels.aurora.component.AuroraBreadcrumbBar
import org.pushingpixels.aurora.component.model.*
Expand Down Expand Up @@ -62,12 +61,44 @@ fun main() = auroraApplication {
}
}

private suspend fun getCommandPanelContent(
contentProvider: BreadcrumbBarContentProvider<File>,
selected: File
): CommandPanelContentModel {
val leaves = contentProvider.getLeaves(selected)
return CommandPanelContentModel(
commandGroups = listOf(
CommandGroup(
title = null,
leaves.map { leaf ->
val extension = leaf.extension.lowercase()

val className =
"org.pushingpixels.aurora.demo.svg.filetypes.ext_${extension}"
var icon: Painter? = null
try {
val transcodedClass = Class.forName(className)
val ctr = transcodedClass.getConstructor()
icon = ctr.newInstance() as Painter
} catch (_: Throwable) {
}

Command(
text = contentProvider.getDisplayText(leaf),
icon = icon,
action = {})
}
)
)
)
}

@Composable
fun AuroraWindowScope.BreadcrumbContent(auroraSkinDefinition: MutableState<AuroraSkinDefinition>) {
val scope = rememberCoroutineScope()

val fileSystemView = FileSystemView.getFileSystemView()
val contentProvider: BreadcrumbBarContentProvider<File> =
val breadcrumbBarContentProvider: BreadcrumbBarContentProvider<File> =
object : BreadcrumbBarContentProvider<File> {
override fun getDisplayText(item: File?): String {
if (item == null) {
Expand Down Expand Up @@ -103,104 +134,22 @@ fun AuroraWindowScope.BreadcrumbContent(auroraSkinDefinition: MutableState<Auror
}
}

val contentModel = remember { mutableStateListOf<Command>() }

suspend fun <T> BreadcrumbBarContentProvider<T>.getPathCommand(
item: T?,
onItemSelected: (T) -> Unit,
level: Int
): Command {
// These will be displayed in the dropdown
val pathChoices = this.getPathChoices(item)

return Command(
text = this.getDisplayText(item),
icon = this.getIcon(item),
action = {
// This is called when the path item is clicked
while (contentModel.size > level) {
contentModel.removeLast()
}
onItemSelected.invoke(item!!)
},
secondaryContentModel = if (pathChoices.isNotEmpty()) CommandMenuContentModel(
group = CommandGroup(title = null,
commands = pathChoices.map { pathChoice ->
Command(text = this.getDisplayText(pathChoice),
icon = this.getIcon(pathChoice),
action = {
// This is called when a dropdown item is clicked
while (contentModel.size > level) {
contentModel.removeLast()
}
scope.launch {
contentModel.add(
getPathCommand(
item = pathChoice,
onItemSelected = onItemSelected,
level = level + 1
)
)
onItemSelected.invoke(pathChoice)
}
})
}
)
) else null
)
}

suspend fun getCommandPanelContent(selected: File): CommandPanelContentModel {
val leaves = contentProvider.getLeaves(selected)
return CommandPanelContentModel(
commandGroups = listOf(
CommandGroup(
title = null,
leaves.map { leaf ->
val extension = leaf.extension.lowercase()

val className =
"org.pushingpixels.aurora.demo.svg.filetypes.ext_${extension}"
var icon: Painter? = null
try {
val transcodedClass = Class.forName(className)
val ctr = transcodedClass.getConstructor()
icon = ctr.newInstance() as Painter
} catch (_: Throwable) {
}

Command(
text = contentProvider.getDisplayText(leaf),
icon = icon,
action = {})
}
)
)
)
}

val commandPanelContentModel = remember { mutableStateOf<CommandPanelContentModel?>(null) }
LaunchedEffect(null) {
coroutineScope {
// Root content for the breadcrumb bar
contentModel.add(
contentProvider.getPathCommand(
item = null,
onItemSelected = { selected: File ->
scope.launch {
commandPanelContentModel.value = getCommandPanelContent(selected)
}
},
level = 1
)
)
val onBreadcrumbItemSelected: (File) -> Unit = {
scope.launch {
commandPanelContentModel.value = getCommandPanelContent(breadcrumbBarContentProvider, it)
}
}

val breadcrumbBarContentModel = BreadcrumbBarContentModel(
contentProvider = breadcrumbBarContentProvider,
onItemSelected = onBreadcrumbItemSelected
)

Column(modifier = Modifier.fillMaxSize()) {
AuroraDecorationArea(decorationAreaType = DecorationAreaType.Header) {
AuroraBreadcrumbBar(
contentModel = contentModel,
contentModel = breadcrumbBarContentModel,
presentationModel = BreadcrumbBarPresentationModel(
iconActiveFilterStrategy = IconFilterStrategy.ThemedFollowText,
iconEnabledFilterStrategy = IconFilterStrategy.ThemedFollowText,
Expand Down Expand Up @@ -255,23 +204,20 @@ fun AuroraWindowScope.BreadcrumbContent(auroraSkinDefinition: MutableState<Auror
currentFile = fileSystemView.getParentDirectory(currentFile)
}
// Convert to list of commands
contentModel.clear()
breadcrumbBarContentModel.clear()
for ((index, file) in filePath.withIndex()) {
contentModel.add(
contentProvider.getPathCommand(
breadcrumbBarContentModel.add(
breadcrumbBarContentProvider.getPathCommand(
scope = scope,
commands = breadcrumbBarContentModel,
item = file,
onItemSelected = { selected: File ->
scope.launch {
commandPanelContentModel.value =
getCommandPanelContent(selected)
}
},
onItemSelected = onBreadcrumbItemSelected,
level = index + 1
)
)
}
commandPanelContentModel.value =
getCommandPanelContent(selected)
getCommandPanelContent(breadcrumbBarContentProvider, selected)
}
}
}),
Expand Down

0 comments on commit f471f81

Please sign in to comment.