2025-12-26 17:45:37 +05:00
|
|
|
|
package ui
|
|
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
import (
|
|
|
|
|
|
"github.com/charmbracelet/lipgloss"
|
|
|
|
|
|
)
|
2025-12-26 17:45:37 +05:00
|
|
|
|
|
2025-12-29 17:46:48 +05:00
|
|
|
|
const (
|
2026-01-14 18:08:43 +05:00
|
|
|
|
ApplicationMinWidth = 60
|
|
|
|
|
|
ApplicationMaxHeight = 40
|
|
|
|
|
|
ApplicationMinHeight = 20
|
|
|
|
|
|
ApplicationHorizontalOffset = 3
|
|
|
|
|
|
ApplicationVerticalOffset = 1
|
|
|
|
|
|
ApplicationContainerPadding = 4
|
|
|
|
|
|
|
|
|
|
|
|
ModalMaxWidth = 50
|
|
|
|
|
|
ModalMaxHeight = 15
|
2025-12-29 17:46:48 +05:00
|
|
|
|
ListWithRatio = 0.4
|
2026-01-14 18:08:43 +05:00
|
|
|
|
TableWithRatio = 0.8
|
2025-12-29 17:46:48 +05:00
|
|
|
|
)
|
|
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
// ContentSizes вычисляет размеры для контейнера внутри окна и контента внутри контейнера.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Принимает 2 параметра типа int, screenWidth и screenHeight ширина и высота окна.
|
|
|
|
|
|
//
|
|
|
|
|
|
// Возвращает 4 значения типа int.
|
|
|
|
|
|
//
|
|
|
|
|
|
// containerWidth это ширина контейнера внутри окна с отступами от левого и правого краёв, и с учетом границ
|
|
|
|
|
|
//
|
|
|
|
|
|
// containerHeight это высота контейнера внутри окна с отступами от верхнего и нижнего краёв, и с учетом границ
|
|
|
|
|
|
//
|
|
|
|
|
|
// contentWidth это ширина контента внутри контейнера с отступами от левого и правого краёв контейнера
|
|
|
|
|
|
//
|
|
|
|
|
|
// contentHeight это высота контента внутри контейнера с отступами от верхнего и нижнего краёв контейнера
|
|
|
|
|
|
func ContentSizes(screenWidth, screenHeight int) (containerWidth, containerHeight, contentWidth, contentHeight int) {
|
|
|
|
|
|
containerWidth = screenWidth - 2*ApplicationHorizontalOffset
|
|
|
|
|
|
if containerWidth < ApplicationMinWidth {
|
|
|
|
|
|
//если ширина слишком маленькая ставим минимальную поддерживаемую
|
|
|
|
|
|
containerWidth = ApplicationMinWidth
|
2025-12-29 17:46:48 +05:00
|
|
|
|
}
|
2026-01-14 18:08:43 +05:00
|
|
|
|
containerWidth = containerWidth - 2*1
|
|
|
|
|
|
//Вычитаем из ширины контейнера 2 условных единицы для границ
|
|
|
|
|
|
//Пример, окно 70, контейнер будет 64, места для контента тогда 62
|
|
|
|
|
|
|
|
|
|
|
|
containerHeight = screenHeight - 2*ApplicationVerticalOffset
|
|
|
|
|
|
if containerHeight < ApplicationMinHeight {
|
|
|
|
|
|
//если высота слишком маленькая ставим минимально поддерживаемую
|
|
|
|
|
|
containerHeight = ApplicationMinHeight
|
2025-12-29 17:46:48 +05:00
|
|
|
|
}
|
2026-01-14 18:08:43 +05:00
|
|
|
|
containerHeight = containerHeight - 2*1
|
|
|
|
|
|
//Вычитаем из высоты контейнера 2 условных единицы для границ
|
|
|
|
|
|
//Пример, окно 30, контейнер будет 28, места для контента тогда 26
|
|
|
|
|
|
|
|
|
|
|
|
contentWidth = containerWidth - 2*ApplicationHorizontalOffset
|
|
|
|
|
|
//Вычитаем из ширины контейнера отступы для контента внутри
|
|
|
|
|
|
contentHeight = containerHeight - 2*ApplicationVerticalOffset
|
|
|
|
|
|
//Вычитаем из высоты контейнера отступы для контента внутри
|
|
|
|
|
|
return
|
2025-12-29 17:46:48 +05:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
// Используемые цвета
|
2025-12-26 17:45:37 +05:00
|
|
|
|
var (
|
2025-12-29 17:46:48 +05:00
|
|
|
|
ColorFg = lipgloss.Color("#eeeeee")
|
|
|
|
|
|
ColorBg = lipgloss.Color("#0d1117")
|
|
|
|
|
|
ColorAccent = lipgloss.Color("#a6e3a1")
|
|
|
|
|
|
ColorAccent2 = lipgloss.Color("#747cec")
|
|
|
|
|
|
ColorWarning = lipgloss.Color("#f9e2af")
|
|
|
|
|
|
ColorError = lipgloss.Color("#f38ba8")
|
|
|
|
|
|
ColorPurple = lipgloss.Color("#cba6f7")
|
|
|
|
|
|
ColorGrey = lipgloss.Color("#585b70")
|
|
|
|
|
|
ColorDarkGrey = lipgloss.Color("#313244")
|
2026-01-14 18:08:43 +05:00
|
|
|
|
)
|
2025-12-29 17:46:48 +05:00
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
var AppContainer = lipgloss.NewStyle().
|
|
|
|
|
|
Padding(ApplicationVerticalOffset, ApplicationHorizontalOffset).
|
|
|
|
|
|
Border(lipgloss.RoundedBorder()).
|
|
|
|
|
|
BorderForeground(ColorAccent)
|
|
|
|
|
|
|
|
|
|
|
|
// Стили для списка приложений
|
|
|
|
|
|
var (
|
|
|
|
|
|
ListTitleStyle = lipgloss.NewStyle().Foreground(ColorPurple).Italic(true).Bold(true)
|
|
|
|
|
|
ListSelectedStyle = lipgloss.NewStyle().Foreground(ColorError).Bold(true)
|
|
|
|
|
|
ListDescriptionStyle = lipgloss.NewStyle().Foreground(ColorAccent2)
|
|
|
|
|
|
)
|
2025-12-29 17:46:48 +05:00
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
// Стили для about
|
|
|
|
|
|
var (
|
|
|
|
|
|
AboutTitle = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorAccent).
|
2025-12-29 17:46:48 +05:00
|
|
|
|
Bold(true).
|
2026-01-14 18:08:43 +05:00
|
|
|
|
AlignHorizontal(lipgloss.Center)
|
|
|
|
|
|
|
|
|
|
|
|
AboutH2 = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorAccent).
|
|
|
|
|
|
Bold(true)
|
|
|
|
|
|
|
|
|
|
|
|
AboutH3 = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorAccent).
|
|
|
|
|
|
Bold(true)
|
|
|
|
|
|
|
|
|
|
|
|
AboutBullet = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorGrey)
|
|
|
|
|
|
|
|
|
|
|
|
AboutNormal = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorFg)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Стили для форм и полей ввода
|
|
|
|
|
|
var (
|
|
|
|
|
|
FormFieldFocused = lipgloss.NewStyle().Foreground(ColorError).Bold(true)
|
|
|
|
|
|
FormFieldUnfocused = lipgloss.NewStyle().Foreground(ColorAccent2)
|
|
|
|
|
|
FormNextButton = lipgloss.NewStyle().Foreground(ColorPurple).Bold(true)
|
|
|
|
|
|
|
|
|
|
|
|
SelectFileDirDeniedStyle = lipgloss.NewStyle().Foreground(ColorGrey)
|
|
|
|
|
|
SelectFileDirParentStyle = lipgloss.NewStyle().Foreground(ColorPurple)
|
|
|
|
|
|
SelectFileStyle = lipgloss.NewStyle().Foreground(ColorAccent)
|
|
|
|
|
|
SelectDirStyle = lipgloss.NewStyle().Foreground(ColorAccent2)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Стили для таблицы переменных Final
|
|
|
|
|
|
var (
|
|
|
|
|
|
FinalHeader = lipgloss.NewStyle().
|
2025-12-29 17:46:48 +05:00
|
|
|
|
Background(ColorDarkGrey).
|
2026-01-14 18:08:43 +05:00
|
|
|
|
Foreground(ColorPurple).
|
|
|
|
|
|
Bold(true).
|
|
|
|
|
|
Align(lipgloss.Center).
|
2025-12-29 17:46:48 +05:00
|
|
|
|
MarginBottom(1).
|
2026-01-14 18:08:43 +05:00
|
|
|
|
Padding(1, 2)
|
2025-12-29 17:46:48 +05:00
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
FinalFooter = lipgloss.NewStyle().
|
2025-12-29 17:46:48 +05:00
|
|
|
|
Foreground(ColorGrey).
|
|
|
|
|
|
MarginTop(1).
|
2026-01-14 18:08:43 +05:00
|
|
|
|
Padding(1, 0).
|
2025-12-29 17:46:48 +05:00
|
|
|
|
Align(lipgloss.Center)
|
|
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
FinalTableBorder = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorPurple)
|
2025-12-29 17:46:48 +05:00
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
FinalTableHeader = lipgloss.NewStyle().
|
|
|
|
|
|
Foreground(ColorPurple).
|
|
|
|
|
|
Bold(true).
|
|
|
|
|
|
Align(lipgloss.Center).
|
|
|
|
|
|
Padding(0, 1)
|
|
|
|
|
|
|
|
|
|
|
|
FinalTableEvenRow = lipgloss.NewStyle().
|
|
|
|
|
|
Background(ColorDarkGrey).
|
|
|
|
|
|
Padding(0, 2)
|
|
|
|
|
|
|
|
|
|
|
|
FinalTableOddRow = lipgloss.NewStyle().
|
|
|
|
|
|
Padding(0, 2)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
// Стили для модальных окон
|
|
|
|
|
|
var (
|
|
|
|
|
|
ModalContainer = lipgloss.NewStyle().
|
|
|
|
|
|
Border(lipgloss.DoubleBorder()).
|
|
|
|
|
|
Align(lipgloss.Center, lipgloss.Center)
|
|
|
|
|
|
//Padding(ApplicationVerticalOffset, ApplicationHorizontalOffset)
|
2025-12-26 17:45:37 +05:00
|
|
|
|
|
2025-12-29 17:46:48 +05:00
|
|
|
|
ModalBorderError = lipgloss.NewStyle().BorderForeground(ColorError)
|
|
|
|
|
|
ModalBorderWarning = lipgloss.NewStyle().BorderForeground(ColorWarning)
|
|
|
|
|
|
ModalBorderConfirm = lipgloss.NewStyle().BorderForeground(ColorPurple)
|
|
|
|
|
|
ModalBorderInfo = lipgloss.NewStyle().BorderForeground(ColorAccent)
|
|
|
|
|
|
|
|
|
|
|
|
ModalTitleError = lipgloss.NewStyle().BorderForeground(ColorError).Bold(true)
|
|
|
|
|
|
ModalTitleWarning = lipgloss.NewStyle().BorderForeground(ColorWarning).Bold(true)
|
|
|
|
|
|
ModalTitleDefault = lipgloss.NewStyle().BorderForeground(ColorPurple).Bold(true)
|
|
|
|
|
|
|
|
|
|
|
|
ModalButtonNormal = lipgloss.NewStyle().
|
|
|
|
|
|
Padding(0, 3).
|
|
|
|
|
|
Border(lipgloss.RoundedBorder()).
|
|
|
|
|
|
BorderForeground(ColorGrey).
|
|
|
|
|
|
Foreground(ColorAccent2)
|
|
|
|
|
|
|
|
|
|
|
|
ModalButtonFocused = lipgloss.NewStyle().
|
|
|
|
|
|
Padding(0, 3).
|
|
|
|
|
|
Border(lipgloss.RoundedBorder()).
|
|
|
|
|
|
BorderForeground(ColorError).
|
|
|
|
|
|
Foreground(ColorError).
|
|
|
|
|
|
Bold(true)
|
2025-12-26 17:45:37 +05:00
|
|
|
|
)
|
2025-12-29 17:46:48 +05:00
|
|
|
|
|
2026-01-14 18:08:43 +05:00
|
|
|
|
//Старые стили
|
|
|
|
|
|
//var (
|
|
|
|
|
|
//ColorWhite = lipgloss.Color("#ffffff")
|
|
|
|
|
|
//ColorGrey = lipgloss.Color("#626262")
|
|
|
|
|
|
//ColorBlack = lipgloss.Color("#000000")
|
|
|
|
|
|
//ColorRed = lipgloss.Color("#FF0000")
|
|
|
|
|
|
//ColorGreen = lipgloss.Color("#00FF00")
|
|
|
|
|
|
//ColorBlue = lipgloss.Color("#0000FF")
|
|
|
|
|
|
//ColorPurple = lipgloss.Color("#6f03fc")
|
|
|
|
|
|
//ColorGreenCyan = lipgloss.Color("#11CAAA")
|
|
|
|
|
|
//
|
|
|
|
|
|
//AppContainerStyle = lipgloss.NewStyle().
|
|
|
|
|
|
// Padding(1, 3).
|
|
|
|
|
|
// Border(lipgloss.RoundedBorder()).
|
|
|
|
|
|
// BorderForeground(ColorPurple)
|
|
|
|
|
|
//
|
|
|
|
|
|
//AppHeaderStyle = lipgloss.NewStyle().
|
|
|
|
|
|
// Bold(true).
|
|
|
|
|
|
// Foreground(ColorPurple).
|
|
|
|
|
|
// Align(lipgloss.Center).
|
|
|
|
|
|
// Padding(1, 0).
|
|
|
|
|
|
// Background(ColorWhite).
|
|
|
|
|
|
// Foreground(ColorBlack)
|
|
|
|
|
|
//
|
|
|
|
|
|
//AppFooterStyle = lipgloss.NewStyle().
|
|
|
|
|
|
// Foreground(ColorGrey).
|
|
|
|
|
|
// Align(lipgloss.Center).
|
|
|
|
|
|
// Padding(0, 1)
|
|
|
|
|
|
//
|
|
|
|
|
|
//TableHeaderStyle = lipgloss.NewStyle().Foreground(ColorPurple).Bold(true).Align(lipgloss.Center)
|
|
|
|
|
|
//TableCellStyle = lipgloss.NewStyle().Padding(0, 1).Width(14)
|
|
|
|
|
|
//TableOddRowStyle = TableCellStyle.Foreground(ColorWhite).Background(ColorGrey)
|
|
|
|
|
|
//TableEvenRowStyle = TableCellStyle.Foreground(ColorWhite)
|
|
|
|
|
|
//TableBorderStyle = lipgloss.NewStyle().Foreground(ColorPurple)
|
|
|
|
|
|
//
|
|
|
|
|
|
//
|
|
|
|
|
|
//SelectStyle = lipgloss.NewStyle().Foreground(ColorGreenCyan)
|
|
|
|
|
|
//InputStyle = lipgloss.NewStyle().Foreground(ColorGreenCyan)
|
|
|
|
|
|
//ComputeStyle = lipgloss.NewStyle().Foreground(ColorGrey)
|
|
|
|
|
|
//CheckboxStyle = lipgloss.NewStyle().Foreground(ColorGreenCyan)
|
|
|
|
|
|
//
|
|
|
|
|
|
//FormFocusedStyle = lipgloss.NewStyle().Foreground(ColorRed).Bold(true).
|
|
|
|
|
|
// Border(lipgloss.NormalBorder(), false, false, false, true).BorderForeground(ColorRed)
|
|
|
|
|
|
//FormUnfocusedStyle = lipgloss.NewStyle().Foreground(ColorGreenCyan)
|
|
|
|
|
|
//FormStyle = lipgloss.NewStyle().Padding(1, 2).Foreground(ColorBlack).
|
|
|
|
|
|
// Border(lipgloss.RoundedBorder()).BorderForeground(ColorRed)
|
|
|
|
|
|
//
|
|
|
|
|
|
//ListStyle = lipgloss.NewStyle().Padding(1, 3).Border(lipgloss.RoundedBorder()).BorderForeground(ColorRed)
|
|
|
|
|
|
//ListSelectedItemStyle = lipgloss.NewStyle().Foreground(ColorRed).Bold(true)
|
|
|
|
|
|
//ListTitleStyle = lipgloss.NewStyle().Foreground(ColorPurple).Italic(true)
|
|
|
|
|
|
//ListDescriptionStyle = lipgloss.NewStyle().Foreground(ColorGreenCyan).MarginTop(1)
|
|
|
|
|
|
//)
|