Pith - wedge_android
wedge_android/app/src/main/java/com/vgmlr/wedge/WedgeEditorComponents.kt [18.2 kb]
Modified: 06:16:54 91 026 (18 Jun 026)
6 Days Ago
package com.vgmlr.wedge

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Undo
import androidx.compose.material.icons.automirrored.outlined.ExitToApp
import androidx.compose.material.icons.automirrored.outlined.Sort
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun EditorTopBar(
    menuExpanded: Boolean,
    onMenuExpandedChange: (Boolean) -> Unit,
    showCopyDot: Boolean,
    showPasteDot: Boolean,
    undoEnabled: Boolean,
    onCopy: () -> Unit,
    onPaste: () -> Unit,
    onUndo: () -> Unit,
    onSelectAll: () -> Unit,
    onSort: () -> Unit,
    onToggleCalc: () -> Unit,
    showCalc: Boolean,
    onShowData: () -> Unit,
    onExport: () -> Unit,
    onSettings: () -> Unit,
    onShowVersion: () -> Unit,
    isEncrypted: Boolean,
    onSecurityAction: () -> Unit,
    // onSync: () -> Unit
) {
    TopAppBar(
        title = { },
        colors = TopAppBarDefaults.topAppBarColors(containerColor = colorResource(id = R.color.primary_color)),
        actions = {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text("wedge", color = colorResource(id = R.color.title_color), fontSize = 18.sp)
                Spacer(Modifier.width(10.dp))
                IconButton(
                    onClick = onUndo,
                    enabled = undoEnabled
                ) {
                    Icon(
                        Icons.AutoMirrored.Filled.Undo,
                        contentDescription = "Undo",
                        tint = if (undoEnabled) colorResource(id = R.color.title_color) else colorResource(id = R.color.title_color).copy(alpha = 0.3f)
                    )
                }
                IconButton(onClick = onCopy) {
                    Box {
                        Icon(Icons.Outlined.ContentCopy, "Copy", tint = colorResource(id = R.color.title_color))
                        if (showCopyDot) {
                            Box(
                                modifier = Modifier
                                    .size(6.dp)
                                    .align(Alignment.TopEnd)
                                    .background(
                                        colorResource(id = R.color.title_color),
                                        shape = androidx.compose.foundation.shape.CircleShape
                                    )
                            )
                        }
                    }
                }
                IconButton(onClick = onPaste) {
                    Box {
                        Icon(Icons.Outlined.ContentPaste, "Paste", tint = colorResource(id = R.color.title_color))
                        if (showPasteDot) {
                            Box(
                                modifier = Modifier
                                    .size(6.dp)
                                    .align(Alignment.TopEnd)
                                    .background(
                                        colorResource(id = R.color.title_color),
                                        shape = androidx.compose.foundation.shape.CircleShape
                                    )
                            )
                        }
                    }
                }
                IconButton(onClick = onSort) {
                    Box {
                        Icon(Icons.AutoMirrored.Outlined.Sort, "Sort", tint = colorResource(id = R.color.title_color))
                    }
                }
                Box {
                    IconButton(onClick = { onMenuExpandedChange(true) }) {
                        Icon(Icons.Default.MoreVert, null, tint = colorResource(id = R.color.title_color))
                    }
                    DropdownMenu(
                        expanded = menuExpanded,
                        onDismissRequest = { onMenuExpandedChange(false) },
                        modifier = Modifier
                            .background(colorResource(id = R.color.menu_bg_color))
                            .padding(horizontal = 6.dp)
                    ) {
                        DropdownMenuItem(
                            text = { Text("Select All", color = colorResource(id = R.color.menu_color)) },
                            onClick = onSelectAll,
                            leadingIcon = { Icon(Icons.Outlined.SelectAll, null, tint = colorResource(id = R.color.menu_color)) }
                        )
                        HorizontalDivider(
                            modifier = Modifier.padding(vertical = 8.dp),
                            color = colorResource(id = R.color.hr_color).copy(0.4f),
                            thickness = 1.dp
                        )
                        DropdownMenuItem(
                            text = { Text(if (isEncrypted) "Decrypt" else "Encrypt", color = colorResource(id = R.color.menu_color)) },
                            onClick = onSecurityAction,
                            leadingIcon = {
                                Icon(
                                    if (isEncrypted) Icons.Outlined.LockOpen else Icons.Outlined.Lock,
                                    null,
                                    tint = colorResource(id = R.color.menu_color)
                                )
                            }
                        )
                        DropdownMenuItem(
                            text = { Text("Sync", color = colorResource(id = R.color.menu_color)) },
                            onClick = onSettings,
                            leadingIcon = { Icon(Icons.Outlined.Loop, null, tint = colorResource(id = R.color.menu_color)) }
                        )
                        DropdownMenuItem(
                            text = { Text("Export", color = colorResource(id = R.color.menu_color)) },
                            onClick = onExport,
                            leadingIcon = { Icon(Icons.AutoMirrored.Outlined.ExitToApp, null, tint = colorResource(id = R.color.menu_color)) }
                        )
                        HorizontalDivider(
                            modifier = Modifier.padding(vertical = 8.dp),
                            color = colorResource(id = R.color.hr_color).copy(0.4f),
                            thickness = 1.dp
                        )
                        DropdownMenuItem(
                            text = { Text("Data", color = colorResource(id = R.color.menu_color)) },
                            onClick = onShowData,
                            leadingIcon = { Icon(Icons.Outlined.DataArray, null, tint = colorResource(id = R.color.menu_color)) }
                        )
                        DropdownMenuItem(
                            text = { Text("Settings", color = colorResource(id = R.color.menu_color)) },
                            onClick = onSettings,
                            leadingIcon = { Icon(Icons.Outlined.Settings, null, tint = colorResource(id = R.color.menu_color)) }
                        )
                        DropdownMenuItem(
                            text = { Text("Version", color = colorResource(id = R.color.menu_color)) },
                            onClick = onShowVersion,
                            leadingIcon = { Icon(Icons.Outlined.History, null, tint = colorResource(id = R.color.menu_color)) }
                        )
                    }
                }
            }
        }
    )
}

@Composable
fun CalculatorOverlay(
    calcValue: String,
    onCalcValueChange: (String) -> Unit,
    onDismiss: () -> Unit,
    focusRequester: FocusRequester
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(52.dp)
            .background(colorResource(id = R.color.calc_bg_color))
    ) {
        IconButton(
            onClick = { if (calcValue.isEmpty()) onDismiss() else onCalcValueChange("") },
            modifier = Modifier.align(Alignment.CenterStart)
        ) { Icon(Icons.Default.Clear, null, tint = colorResource(id = R.color.calc_color).copy(alpha = 0.4f)) }
        BasicTextField(
            value = calcValue,
            onValueChange = { onCalcValueChange(if (it.endsWith("=")) WedgeCalculator.doCalc(it.dropLast(1)) else it) },
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 48.dp, end = 22.dp)
                .align(Alignment.Center)
                .focusRequester(focusRequester),
            textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 19.sp, textAlign = TextAlign.End, fontFamily = FontFamily.Monospace),
            cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
            keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
            keyboardActions = KeyboardActions(onDone = { onCalcValueChange(WedgeCalculator.doCalc(calcValue)) }),
            singleLine = true,
            decorationBox = { inner ->
                Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
                    if (calcValue.isEmpty()) Text("0", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.6f), fontSize = 19.sp, textAlign = TextAlign.End, fontFamily = FontFamily.Monospace))
                    inner()
                }
            }
        )
    }
}

@Composable
fun EncryptionOverlay(
    passPhrase: String,
    onPassPhraseChange: (String) -> Unit,
    onAction: () -> Unit,
    onDismiss: () -> Unit,
    focusRequester: FocusRequester,
    isDecrypt: Boolean = false
) {
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(52.dp)
            .background(colorResource(id = R.color.calc_bg_color))
    ) {
        IconButton(
            onClick = onAction,
            enabled = passPhrase.isNotEmpty(),
            modifier = Modifier.align(Alignment.CenterStart)
        ) {
            Icon(
                if (isDecrypt) Icons.Outlined.LockOpen else Icons.Outlined.Lock,
                contentDescription = null,
                modifier = Modifier.padding(start = 3.dp),
                tint = if (passPhrase.isNotEmpty()) colorResource(id = R.color.calc_color) else colorResource(id = R.color.calc_color).copy(alpha = 0.4f)
            )
        }
        BasicTextField(
            value = passPhrase,
            onValueChange = onPassPhraseChange,
            modifier = Modifier
                .fillMaxWidth()
                .padding(start = 58.dp, end = 48.dp)
                .align(Alignment.Center)
                .focusRequester(focusRequester),
            textStyle = TextStyle(
                colorResource(id = R.color.calc_color),
                fontSize = 16.sp,
                textAlign = TextAlign.Start,
                fontFamily = FontFamily.Monospace
            ),
            cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
            visualTransformation = PasswordVisualTransformation(),
            keyboardOptions = KeyboardOptions(
                imeAction = ImeAction.Done,
                keyboardType = KeyboardType.Password
            ),
            keyboardActions = KeyboardActions(onDone = { if(passPhrase.isNotEmpty()) onAction() }),
            singleLine = true,
            decorationBox = { inner ->
                Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterStart) {
                    if (passPhrase.isEmpty()) Text(
                        if (isDecrypt) "Pass Phrase" else "Pass Phrase",
                        style = TextStyle(
                            colorResource(id = R.color.calc_color).copy(alpha = 0.6f),
                            fontSize = 16.sp,
                            textAlign = TextAlign.Start,
                            fontFamily = FontFamily.Monospace
                        )
                    )
                    inner()
                }
            }
        )
        IconButton(
            onClick = onDismiss,
            modifier = Modifier
                .align(Alignment.CenterEnd)
                .padding(end = 3.dp),
        ) { Icon(Icons.Default.Clear, null, tint = colorResource(id = R.color.calc_color).copy(alpha = 0.4f)) }
    }
}

@Composable
fun CalendarOverlay(
    daySelected: String,
    onDaySelectedChange: (String) -> Unit,
    timeValue: String,
    onTimeValueChange: (String) -> Unit,
    textValue: String,
    onTextValueChange: (String) -> Unit,
    onDismiss: () -> Unit,
    onEnterPressed: () -> Unit,
    focusRequester: FocusRequester
) {
    val focusManager = LocalFocusManager.current
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(52.dp)
            .background(colorResource(id = R.color.calc_bg_color))
    ) {
        Row(
            modifier = Modifier
                .fillMaxSize()
                .padding(start = 8.dp, end = 8.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(7.dp)
        ) {
            BasicTextField(
                value = daySelected,
                onValueChange = onDaySelectedChange,
                modifier = Modifier
                    .width(40.dp)
                    .padding(end = 4.dp),
                textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 16.sp, fontFamily = FontFamily.Monospace, textAlign = TextAlign.End),
                cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
                singleLine = true,
                decorationBox = { inner ->
                    Box(contentAlignment = Alignment.CenterEnd) {
                        if (daySelected.isEmpty()) Text("Date", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.5f), fontSize = 16.sp, textAlign = TextAlign.End))
                        inner()
                    }
                }
            )

            BasicTextField(
                value = timeValue,
                onValueChange = { if (it.length <= 5) onTimeValueChange(it) },
                modifier = Modifier
                    .width(65.dp)
                    .background(
                        Color.White.copy(alpha = 0.05f),
                        androidx.compose.foundation.shape.RoundedCornerShape(4.dp)
                    )
                    .padding(8.dp)
                    .focusRequester(focusRequester)
                    .onPreviewKeyEvent { keyEvent ->
                        if (keyEvent.key == Key.Enter || keyEvent.key == Key.NumPadEnter) {
                            focusManager.moveFocus(FocusDirection.Next)
                            true
                        } else {
                            false
                        }
                    },
                textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 16.sp, fontFamily = FontFamily.Monospace, textAlign = TextAlign.Center),
                cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
                singleLine = true,
                keyboardOptions = KeyboardOptions(
                    keyboardType = KeyboardType.Number,
                    imeAction = ImeAction.Next
                ),
                keyboardActions = KeyboardActions(
                    onNext = { focusManager.moveFocus(FocusDirection.Next) }
                ),
                decorationBox = { inner ->
                    Box(contentAlignment = Alignment.Center) {
                        if (timeValue.isEmpty()) Text("HHMM", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.5f), fontSize = 16.sp, fontFamily = FontFamily.Monospace, textAlign = TextAlign.Center))
                        inner()
                    }
                }
            )

            BasicTextField(
                value = textValue,
                onValueChange = onTextValueChange,
                modifier = Modifier
                    .weight(1f)
                    .background(
                        Color.White.copy(alpha = 0.05f),
                        androidx.compose.foundation.shape.RoundedCornerShape(4.dp)
                    )
                    .padding(8.dp),
                textStyle = TextStyle(colorResource(id = R.color.calc_color), fontSize = 16.sp, fontFamily = FontFamily.Monospace),
                cursorBrush = SolidColor(colorResource(id = R.color.calc_color)),
                singleLine = true,
                keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
                keyboardActions = KeyboardActions(onDone = { onEnterPressed() }),
                decorationBox = { inner ->
                    Box(contentAlignment = Alignment.CenterStart) {
                        if (textValue.isEmpty()) Text("Event", style = TextStyle(colorResource(id = R.color.calc_color).copy(alpha = 0.5f), fontSize = 16.sp, fontFamily = FontFamily.Monospace))
                        inner()
                    }
                }
            )

            IconButton(
                onClick = onDismiss,
                modifier = Modifier.size(36.dp)
            ) {
                Icon(Icons.Default.Clear, null, tint = colorResource(id = R.color.calc_color).copy(alpha = 0.6f))
            }
        }
    }
}
Updates
OTC Applet - Linux 93.026.1
Wedge - Linux 90.026.1
Wedge - Android 90.026.1
Shim - Android 86.026.1
Kerf - Android 86.026.4
Dev
TVShow (227) 'CSA'
TVShow (228) 'APT'
TVProgram (83) 'BXT'
Miter Update(s)
Peen (Messaging)

Menu
Calendar
Project Tin (024/029)
Miter
RSS Feed
User Avatar
@vgmlr
=SUM(parts)