mirror of
https://github.com/gen2brain/cbconvert
synced 2026-06-30 09:11:54 +02:00
799 lines
26 KiB
Go
799 lines
26 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"image/gif"
|
|
"math"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gen2brain/cbconvert"
|
|
"github.com/gen2brain/cbconvert/cmd/cbconvert-gui/i18n"
|
|
"github.com/gen2brain/iup-go/iup"
|
|
)
|
|
|
|
func setEffort(format string) {
|
|
val := iup.GetHandle("Effort")
|
|
|
|
var name string
|
|
|
|
switch format {
|
|
case "webp":
|
|
val.SetAttributes("MIN=0, MAX=6, SHOWTICKS=7, VALUE=4")
|
|
val.SetAttribute("TIP", i18n.Lng(i18n.TipEffortWebp))
|
|
name = i18n.Str(i18n.EffortMethod)
|
|
case "avif":
|
|
val.SetAttributes("MIN=0, MAX=10, SHOWTICKS=11, VALUE=10")
|
|
val.SetAttribute("TIP", i18n.Lng(i18n.TipEffortAvif))
|
|
name = i18n.Str(i18n.EffortSpeed)
|
|
case "jxl":
|
|
val.SetAttributes("MIN=1, MAX=10, SHOWTICKS=10, VALUE=7")
|
|
val.SetAttribute("TIP", i18n.Lng(i18n.TipEffortJxl))
|
|
name = i18n.Str(i18n.EffortEffort)
|
|
default:
|
|
return
|
|
}
|
|
|
|
val.SetAttribute("EFFORTNAME", name)
|
|
iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", name, val.GetInt("VALUE")))
|
|
iup.Refresh(iup.GetHandle("LabelEffort"))
|
|
}
|
|
|
|
// tableRowColors sets the alternating row colors for dark or light mode.
|
|
func tableRowColors(t iup.Ihandle, dark bool) {
|
|
even, odd := "#F0F0F0", "#FFFFFF"
|
|
if dark {
|
|
even, odd = "#3A3A3A", "#2D2D2D"
|
|
}
|
|
t.SetAttribute("EVENROWCOLOR", even)
|
|
t.SetAttribute("ODDROWCOLOR", odd)
|
|
}
|
|
|
|
func list() iup.Ihandle {
|
|
t := iup.Table().SetHandle("Table")
|
|
t.SetAttributes(map[string]string{
|
|
"EXPAND": "YES",
|
|
"NUMCOL": "3",
|
|
"NUMLIN": "0",
|
|
"TITLE1": i18n.Lng(i18n.ColTitle),
|
|
"TITLE2": i18n.Lng(i18n.ColType),
|
|
"TITLE3": i18n.Lng(i18n.ColSize),
|
|
"WIDTH1": "250",
|
|
"WIDTH2": "50",
|
|
"WIDTH3": "100",
|
|
"ALIGNMENT2": "ACENTER",
|
|
"ALIGNMENT3": "ARIGHT",
|
|
"SELECTIONMODE": "SINGLE",
|
|
"USERRESIZE": "YES",
|
|
"STRETCHLAST": "NO",
|
|
"FOCUSRECT": "NO",
|
|
"SORTABLE": "YES",
|
|
"ALTERNATECOLOR": "YES",
|
|
})
|
|
|
|
tableRowColors(t, iup.GetGlobal("DARKMODE") == "YES" && iup.GetGlobal("AUTODARKMODE") == "YES")
|
|
|
|
t.SetCallback("ENTERITEM_CB", iup.EnterItemFunc(func(ih iup.Ihandle, lin, col int) int {
|
|
index = lin - 1
|
|
setActive()
|
|
previewPost()
|
|
|
|
return iup.DEFAULT
|
|
}))
|
|
|
|
t.SetCallback("SORT_CB", iup.TableSortFunc(onSort))
|
|
|
|
t.SetCallback("DROPFILES_CB", iup.DropFilesFunc(func(ih iup.Ihandle, fileName string, num, x, y int) int {
|
|
dec, err := url.QueryUnescape(fileName)
|
|
if err != nil {
|
|
iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0)
|
|
fmt.Println(err)
|
|
|
|
return iup.DEFAULT
|
|
}
|
|
|
|
conv := cbconvert.New(options())
|
|
|
|
fs, err := conv.Files([]string{dec})
|
|
if err != nil {
|
|
iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0)
|
|
fmt.Println(err)
|
|
|
|
return iup.DEFAULT
|
|
}
|
|
|
|
addFiles(fs)
|
|
|
|
return iup.DEFAULT
|
|
}))
|
|
|
|
return iup.Vbox(t)
|
|
}
|
|
|
|
func preview() iup.Ihandle {
|
|
return iup.Frame(
|
|
iup.Vbox(
|
|
iup.Canvas().SetAttributes("EXPAND=YES, MINSIZE=400x, BORDER=NO").SetHandle("Preview").
|
|
SetCallback("ACTION", iup.ActionFunc(drawPreview)).
|
|
SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(previewMessage)),
|
|
iup.Label("").SetAttributes("EXPAND=HORIZONTAL, ALIGNMENT=ACENTER").SetHandle("PreviewInfo"),
|
|
),
|
|
)
|
|
}
|
|
|
|
// previewTheme holds the preview canvas colors for light or dark mode.
|
|
type previewTheme struct {
|
|
gradTop, gradBottom string
|
|
card, cardBorder string
|
|
frame, shadow string
|
|
}
|
|
|
|
func previewThemeFor(dark bool) previewTheme {
|
|
if dark {
|
|
return previewTheme{
|
|
gradTop: "#3A3F45", gradBottom: "#202327",
|
|
card: "#FFFFFF", cardBorder: "#16181B",
|
|
frame: "#101214", shadow: "#141619",
|
|
}
|
|
}
|
|
|
|
return previewTheme{
|
|
gradTop: "#F7F9FC", gradBottom: "#DBE2EA",
|
|
card: "#FFFFFF", cardBorder: "#CDD5DE",
|
|
frame: "#BFC8D2", shadow: "#B7C0CB",
|
|
}
|
|
}
|
|
|
|
// drawPreview paints a gradient background, then the cover framed with a drop shadow, or an empty page card with the logo.
|
|
func drawPreview(ih iup.Ihandle) int {
|
|
iup.DrawBegin(ih)
|
|
defer iup.DrawEnd(ih)
|
|
|
|
cw, ch := iup.DrawGetSize(ih)
|
|
th := previewThemeFor(iup.GetGlobal("DARKMODE") == "YES" && iup.GetGlobal("AUTODARKMODE") == "YES")
|
|
|
|
iup.DrawLinearGradient(ih, 0, 0, cw, ch, 90, th.gradTop, th.gradBottom)
|
|
|
|
margin := cw / 24
|
|
if m := ch / 24; m < margin {
|
|
margin = m
|
|
}
|
|
if margin < 12 {
|
|
margin = 12
|
|
}
|
|
|
|
if hasCover {
|
|
drawCover(ih, th, cw, ch, margin)
|
|
} else {
|
|
drawPlaceholder(ih, th, cw, ch, margin)
|
|
}
|
|
|
|
return iup.DEFAULT
|
|
}
|
|
|
|
// drawCover draws the loaded cover scaled to fit, with a drop shadow and a thin frame.
|
|
func drawCover(ih iup.Ihandle, th previewTheme, cw, ch, margin int) {
|
|
iw, ihh, _ := iup.DrawGetImageInfo("cover")
|
|
if iw <= 0 || ihh <= 0 {
|
|
return
|
|
}
|
|
|
|
s := math.Min(float64(cw-2*margin)/float64(iw), float64(ch-2*margin)/float64(ihh))
|
|
dw, dh := int(float64(iw)*s), int(float64(ihh)*s)
|
|
x, y := (cw-dw)/2, (ch-dh)/2
|
|
|
|
const off = 6
|
|
ih.SetAttribute("DRAWSTYLE", "FILL")
|
|
ih.SetAttribute("DRAWCOLOR", th.shadow)
|
|
iup.DrawRectangle(ih, x+off, y+off, x+dw+off, y+dh+off)
|
|
|
|
iup.DrawImage(ih, "cover", x, y, dw, dh)
|
|
|
|
ih.SetAttribute("DRAWSTYLE", "STROKE")
|
|
ih.SetAttribute("DRAWLINEWIDTH", "1")
|
|
ih.SetAttribute("DRAWCOLOR", th.frame)
|
|
iup.DrawRectangle(ih, x, y, x+dw, y+dh)
|
|
}
|
|
|
|
// drawPlaceholder draws an empty comic-page card with the logo centered, shown until a cover is loaded.
|
|
func drawPlaceholder(ih iup.Ihandle, th previewTheme, cw, ch, margin int) {
|
|
cardH := ch - 2*margin
|
|
cardW := cardH * 2 / 3
|
|
if cardW > cw-2*margin {
|
|
cardW = cw - 2*margin
|
|
cardH = cardW * 3 / 2
|
|
}
|
|
x, y := (cw-cardW)/2, (ch-cardH)/2
|
|
|
|
r := cardW / 14
|
|
if r < 8 {
|
|
r = 8
|
|
}
|
|
|
|
const off = 7
|
|
ih.SetAttribute("DRAWSTYLE", "FILL")
|
|
ih.SetAttribute("DRAWCOLOR", th.shadow)
|
|
iup.DrawRoundedRectangle(ih, x+off, y+off, x+cardW+off, y+cardH+off, r)
|
|
|
|
ih.SetAttribute("DRAWCOLOR", th.card)
|
|
iup.DrawRoundedRectangle(ih, x, y, x+cardW, y+cardH, r)
|
|
|
|
ih.SetAttribute("DRAWSTYLE", "STROKE")
|
|
ih.SetAttribute("DRAWLINEWIDTH", "1")
|
|
ih.SetAttribute("DRAWCOLOR", th.cardBorder)
|
|
iup.DrawRoundedRectangle(ih, x, y, x+cardW, y+cardH, r)
|
|
|
|
lw, lh, _ := iup.DrawGetImageInfo("logo")
|
|
if lw <= 0 || lh <= 0 {
|
|
return
|
|
}
|
|
|
|
s := float64(cardW*2/5) / float64(lw)
|
|
dw, dh := int(float64(lw)*s), int(float64(lh)*s)
|
|
iup.DrawImage(ih, "logo", x+(cardW-dw)/2, y+(cardH-dh)/2, dw, dh)
|
|
}
|
|
|
|
// previewMessage receives a rendered cover from previewRender and triggers a canvas redraw.
|
|
func previewMessage(ih iup.Ihandle, s string, i int, p any) int {
|
|
if i != previewPage {
|
|
return iup.DEFAULT
|
|
}
|
|
|
|
img := p.(cbconvert.Image)
|
|
iup.GetHandle("Loading").SetAttributes("VISIBLE=NO, STOP=YES")
|
|
|
|
if img.Image != nil && len(s) == 0 {
|
|
iup.Destroy(iup.GetHandle("cover"))
|
|
iup.ImageFromImage(img.Image).SetHandle("cover")
|
|
hasCover = true
|
|
iup.GetHandle("PreviewInfo").SetAttribute("TITLE", fmt.Sprintf("%s (%dx%d)", img.SizeHuman, img.Width, img.Height))
|
|
} else {
|
|
iup.Destroy(iup.GetHandle("cover"))
|
|
hasCover = false
|
|
iup.GetHandle("PreviewInfo").SetAttribute("TITLE", "")
|
|
|
|
sp := strings.Split(s, ": ")
|
|
if len(sp) > 1 {
|
|
iup.MessageError(ih, fmt.Sprintf("%s\n\n%s", sp[0], strings.Join(sp[1:], ": ")))
|
|
}
|
|
}
|
|
|
|
iup.Update(ih)
|
|
|
|
return iup.DEFAULT
|
|
}
|
|
|
|
// pageBox is the page-navigation spin shown in the status bar; hidden until a comic is selected.
|
|
func pageBox() iup.Ihandle {
|
|
return iup.Hbox(
|
|
iup.Space().SetAttribute("SIZE", "5"),
|
|
iup.Label(i18n.Lng(i18n.LblPage)),
|
|
iup.Space().SetAttribute("SIZE", "3"),
|
|
iup.Text().SetAttributes(`SPIN=YES, SPINMIN=1, SPINMAX=1, VALUE=1, VISIBLECOLUMNS=3, MASK="/d*"`).SetHandle("Page").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipPage)).
|
|
SetCallback("SPIN_CB", iup.SpinFunc(func(ih iup.Ihandle, pos int) int {
|
|
return onPageChanged()
|
|
})).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
return onPageChanged()
|
|
})).
|
|
SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int {
|
|
if s != previewPath {
|
|
return iup.DEFAULT
|
|
}
|
|
|
|
ih.SetAttribute("SPINMAX", strconv.Itoa(i))
|
|
iup.GetHandle("PageCount").SetAttribute("TITLE", fmt.Sprintf("/ %d", i))
|
|
|
|
if previewPage > i-1 {
|
|
previewPage = i - 1
|
|
}
|
|
if previewPage < 0 {
|
|
previewPage = 0
|
|
}
|
|
ih.SetAttribute("VALUE", strconv.Itoa(previewPage+1))
|
|
|
|
iup.Refresh(iup.GetHandle("PageBox"))
|
|
|
|
previewRender()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
iup.Space().SetAttribute("SIZE", "3"),
|
|
iup.Label("").SetHandle("PageCount"),
|
|
).SetAttributes("ALIGNMENT=ACENTER, VISIBLE=NO").SetHandle("PageBox")
|
|
}
|
|
|
|
func tabInput() iup.Ihandle {
|
|
return iup.Hbox(
|
|
iup.Vbox(
|
|
iup.Toggle(i18n.Lng(i18n.TglRecursive)).SetHandle("Recursive").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipRecursive)),
|
|
iup.Toggle(i18n.Lng(i18n.TglNoRGB)).SetHandle("NoRGB").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipNoRGB)),
|
|
iup.Toggle(i18n.Lng(i18n.TglNoCover)).SetHandle("NoCover").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipNoCover)),
|
|
iup.Toggle(i18n.Lng(i18n.TglNoNonImage)).SetHandle("NoNonImage").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipNoNonImage)),
|
|
iup.Toggle(i18n.Lng(i18n.TglNoConvert)).SetHandle("NoConvert").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipNoConvert)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setActive()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
).SetAttributes("NGAP=10"),
|
|
iup.Space().SetAttribute("SIZE", "15"),
|
|
iup.Vbox(
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblMinSize)),
|
|
iup.Text().SetAttributes(`SPIN=YES, SPINMAX=2048, VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Size").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipSize)),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblDPI)),
|
|
iup.List().SetAttributes(map[string]string{
|
|
"DROPDOWN": "YES",
|
|
"EDITBOX": "YES",
|
|
"VISIBLECOLUMNS": "6",
|
|
"VALUE": "Default",
|
|
"1": "Default",
|
|
"2": "150",
|
|
"3": "300",
|
|
"4": "600",
|
|
"5": "1200",
|
|
}).SetHandle("DPI").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipDPI)),
|
|
),
|
|
).SetAttributes("NGAP=10"),
|
|
).SetHandle("VboxInput")
|
|
}
|
|
|
|
func tabOutput() iup.Ihandle {
|
|
return iup.Hbox(
|
|
iup.Vbox(
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblOutDir)),
|
|
iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("OutDir").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipOutDir)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setActive()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
iup.Space().SetAttribute("SIZE", "5x0"),
|
|
iup.Button(i18n.Lng(i18n.BtnBrowse)).SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onOutputDirectory)),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblSuffix)),
|
|
iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("Suffix").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipSuffix)),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblArchive)),
|
|
iup.List().SetAttributes(map[string]string{
|
|
"DROPDOWN": "YES",
|
|
"VALUE": "1",
|
|
"1": "ZIP",
|
|
"2": "TAR",
|
|
}).SetHandle("Archive").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipArchive)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setActive()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblCompression)),
|
|
iup.List().SetAttributes(map[string]string{
|
|
"DROPDOWN": "YES",
|
|
"VALUE": "1",
|
|
"1": "Default",
|
|
"2": "Store (none)",
|
|
"3": "1",
|
|
"4": "2",
|
|
"5": "3",
|
|
"6": "4",
|
|
"7": "5",
|
|
"8": "6",
|
|
"9": "7",
|
|
"10": "8",
|
|
"11": "9",
|
|
}).SetHandle("ZipLevel").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipZipLevel)),
|
|
).SetHandle("VboxZipLevel"),
|
|
).SetAttributes("NGAP=10"),
|
|
iup.Space().SetAttribute("SIZE", "15"),
|
|
iup.Vbox(
|
|
iup.Vbox(
|
|
iup.Toggle(i18n.Lng(i18n.TglCombine)).SetHandle("Combine").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipCombine)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setActive()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblOutFile)),
|
|
iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("OutFile").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipOutFile)),
|
|
iup.Space().SetAttribute("SIZE", "5x0"),
|
|
iup.Button(i18n.Lng(i18n.BtnBrowse)).SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onOutputFile)),
|
|
).SetHandle("VboxOutFile"),
|
|
).SetAttributes("NGAP=10"),
|
|
).SetHandle("VboxOutput")
|
|
}
|
|
|
|
func tabImage() iup.Ihandle {
|
|
return iup.Hbox(
|
|
iup.Vbox(
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblFormat)),
|
|
iup.List().SetAttributes(map[string]string{
|
|
"DROPDOWN": "YES",
|
|
"VALUE": "1",
|
|
"1": "JPEG",
|
|
"2": "PNG",
|
|
"3": "TIFF",
|
|
"4": "BMP",
|
|
"5": "WEBP",
|
|
"6": "AVIF",
|
|
"7": "JXL",
|
|
}).SetHandle("Format").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipFormat)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setEffort(strings.ToLower(ih.GetAttribute("VALUESTRING")))
|
|
setActive()
|
|
previewPost()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblSize)),
|
|
iup.Hbox(
|
|
iup.Text().SetAttributes(`VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Width").
|
|
SetAttribute("CUEBANNER", i18n.Lng(i18n.CueWidth)).
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipWidthHeight)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setActive()
|
|
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
|
|
|
|
return iup.DEFAULT
|
|
})).
|
|
SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int {
|
|
if ih.GetAttribute("MYVALUE") != "" {
|
|
previewPost()
|
|
}
|
|
ih.SetAttribute("MYVALUE", "")
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
iup.Space().SetAttribute("SIZE", "2"),
|
|
iup.Label("x"),
|
|
iup.Space().SetAttribute("SIZE", "2"),
|
|
iup.Text().SetAttributes(`VISIBLECOLUMNS=6, MASK="/d*"`).SetHandle("Height").
|
|
SetAttribute("CUEBANNER", i18n.Lng(i18n.CueHeight)).
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipWidthHeight)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
setActive()
|
|
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
|
|
|
|
return iup.DEFAULT
|
|
})).
|
|
SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int {
|
|
if ih.GetAttribute("MYVALUE") != "" {
|
|
previewPost()
|
|
}
|
|
ih.SetAttribute("MYVALUE", "")
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"),
|
|
),
|
|
iup.Vbox(
|
|
iup.Toggle(i18n.Lng(i18n.TglFit)).SetHandle("Fit").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipFit)),
|
|
iup.Toggle(i18n.Lng(i18n.TglNoUpscale)).SetHandle("NoUpscale").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipNoUpscale)),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblFilter)),
|
|
iup.List().SetAttributes(map[string]string{
|
|
"DROPDOWN": "YES",
|
|
"VALUE": "3",
|
|
"TIP": i18n.Lng(i18n.FilterLinear),
|
|
"1": "NearestNeighbor",
|
|
"2": "Box",
|
|
"3": "Linear",
|
|
"4": "MitchellNetravali",
|
|
"5": "CatmullRom",
|
|
"6": "Gaussian",
|
|
"7": "Lanczos",
|
|
}).SetHandle("Filter").SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(onFilterChanged)),
|
|
),
|
|
).SetAttributes("NGAP=10"),
|
|
iup.Space().SetAttribute("SIZE", "15"),
|
|
iup.Vbox(
|
|
iup.Vbox(
|
|
iup.Hbox(
|
|
iup.Label(i18n.Lng(i18n.LblQuality)),
|
|
iup.Label("75").SetHandle("LabelQuality"),
|
|
).SetAttributes("NMARGIN=0"),
|
|
iup.Val("").SetAttributes(`MIN=0, MAX=100, VALUE=75, SHOWTICKS=10`).SetHandle("Quality").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipQuality)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
iup.GetHandle("LabelQuality").SetAttribute("TITLE", ih.GetInt("VALUE"))
|
|
iup.Refresh(iup.GetHandle("LabelQuality"))
|
|
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
|
|
|
|
return iup.DEFAULT
|
|
})).
|
|
SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int {
|
|
if ih.GetAttribute("MYVALUE") != "" {
|
|
previewPost()
|
|
}
|
|
ih.SetAttribute("MYVALUE", "")
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
).SetHandle("VboxQuality"),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblEffort)).SetHandle("LabelEffort"),
|
|
iup.Val("").SetAttributes(`MIN=0, MAX=10, VALUE=0, SHOWTICKS=11`).SetHandle("Effort").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipEffort)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
iup.GetHandle("LabelEffort").SetAttribute("TITLE", fmt.Sprintf("%s: %d", ih.GetAttribute("EFFORTNAME"), ih.GetInt("VALUE")))
|
|
iup.Refresh(iup.GetHandle("LabelEffort"))
|
|
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
|
|
|
|
return iup.DEFAULT
|
|
})).
|
|
SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int {
|
|
if ih.GetAttribute("MYVALUE") != "" {
|
|
previewPost()
|
|
}
|
|
ih.SetAttribute("MYVALUE", "")
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
).SetHandle("VboxEffort"),
|
|
iup.Vbox(
|
|
iup.Toggle(i18n.Lng(i18n.TglLossless)).SetHandle("Lossless").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipLossless)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
userLossless = ih.GetAttribute("VALUE") == "ON"
|
|
setActive()
|
|
previewPost()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
iup.Vbox(
|
|
iup.Toggle(i18n.Lng(i18n.TglGrayscale)).SetHandle("Grayscale").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipGrayscale)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
previewPost()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
).SetAttributes("NGAP=10"),
|
|
).SetHandle("VboxImage")
|
|
}
|
|
|
|
func tabTransform() iup.Ihandle {
|
|
return iup.Vbox(
|
|
iup.Vbox(
|
|
iup.Hbox(
|
|
iup.Label(i18n.Lng(i18n.LblBrightness)),
|
|
iup.Label("0").SetHandle("LabelBrightness"),
|
|
).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"),
|
|
iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Brightness").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipBrightness)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
iup.GetHandle("LabelBrightness").SetAttribute("TITLE", iup.GetHandle("Brightness").GetInt("VALUE"))
|
|
iup.Refresh(iup.GetHandle("LabelBrightness"))
|
|
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
|
|
|
|
return iup.DEFAULT
|
|
})).
|
|
SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int {
|
|
if ih.GetAttribute("MYVALUE") != "" {
|
|
previewPost()
|
|
}
|
|
ih.SetAttribute("MYVALUE", "")
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
iup.Vbox(
|
|
iup.Hbox(
|
|
iup.Label(i18n.Lng(i18n.LblContrast)),
|
|
iup.Label("0").SetHandle("LabelContrast"),
|
|
).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=0"),
|
|
iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Contrast").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipContrast)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
iup.GetHandle("LabelContrast").SetAttribute("TITLE", iup.GetHandle("Contrast").GetInt("VALUE"))
|
|
iup.Refresh(iup.GetHandle("LabelContrast"))
|
|
ih.SetAttribute("MYVALUE", ih.GetInt("VALUE"))
|
|
|
|
return iup.DEFAULT
|
|
})).
|
|
SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int {
|
|
if ih.GetAttribute("MYVALUE") != "" {
|
|
previewPost()
|
|
}
|
|
ih.SetAttribute("MYVALUE", "")
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblRotate)),
|
|
iup.List().SetAttributes(map[string]string{
|
|
"DROPDOWN": "YES",
|
|
"VALUE": "1",
|
|
"1": "0",
|
|
"2": "90",
|
|
"3": "180",
|
|
"4": "270",
|
|
}).SetHandle("Rotate").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipRotate)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int {
|
|
previewPost()
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
),
|
|
).SetHandle("VboxTransform").SetAttributes("NGAP=10")
|
|
}
|
|
|
|
func tabs() iup.Ihandle {
|
|
return iup.Tabs(
|
|
tabInput().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabInput)+", NMARGIN=10x10"),
|
|
tabOutput().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabOutput)+", NMARGIN=10x10"),
|
|
tabImage().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabImage)+", NMARGIN=10x10"),
|
|
tabTransform().SetAttributes("TABTITLE="+i18n.Lng(i18n.TabTransform)+", NMARGIN=10x10"),
|
|
).SetHandle("Tabs")
|
|
}
|
|
|
|
func buttons() iup.Ihandle {
|
|
addFiles := iup.Button(i18n.Lng(i18n.BtnAddFiles)).SetHandle("AddFiles").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onAddFiles))
|
|
addDir := iup.Button(i18n.Lng(i18n.BtnAddDir)).SetHandle("AddDir").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onAddDir))
|
|
remove := iup.Button(i18n.Lng(i18n.BtnRemove)).SetHandle("Remove").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onRemove))
|
|
removeAll := iup.Button(i18n.Lng(i18n.BtnRemoveAll)).SetHandle("RemoveAll").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onRemoveAll))
|
|
thumbnail := iup.Button(i18n.Lng(i18n.BtnThumbnail)).SetHandle("Thumbnail").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onThumbnail))
|
|
cover := iup.Button(i18n.Lng(i18n.BtnCover)).SetHandle("Cover").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onCover))
|
|
convert := iup.Button(i18n.Lng(i18n.BtnConvert)).SetHandle("Convert").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetCallback("ACTION", iup.ActionFunc(onConvert))
|
|
reset := iup.Button(i18n.Lng(i18n.BtnReset)).SetHandle("Reset").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipReset)).
|
|
SetCallback("ACTION", iup.ActionFunc(onReset))
|
|
save := iup.Button(i18n.Lng(i18n.BtnSave)).SetHandle("Save").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipSave)).
|
|
SetCallback("ACTION", iup.ActionFunc(onSave))
|
|
|
|
command := iup.Button(i18n.Lng(i18n.BtnCommand)).SetHandle("Command").SetAttributes("PADDING=DEFAULTBUTTONPADDING").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipCommand)).
|
|
SetCallback("ACTION", iup.ActionFunc(onCommand))
|
|
|
|
profile := iup.List().SetAttributes("DROPDOWN=YES").SetHandle("Profile").
|
|
SetAttribute("TIP", i18n.Lng(i18n.TipProfile)).
|
|
SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(onProfileSelect))
|
|
|
|
iup.Normalizer(addFiles, addDir, remove, removeAll, thumbnail, cover, convert, reset, save, command).SetAttribute("NORMALIZE", "BOTH")
|
|
iup.Normalizer(addFiles, addDir, remove, removeAll, thumbnail, cover, convert, reset, save, command, profile).SetAttribute("NORMALIZE", "HORIZONTAL")
|
|
|
|
return iup.Vbox(
|
|
iup.Vbox(
|
|
addFiles,
|
|
addDir,
|
|
remove,
|
|
removeAll,
|
|
).SetAttribute("NGAP", "2"),
|
|
iup.Space().SetAttribute("SIZE", "x5"),
|
|
iup.Vbox(
|
|
thumbnail,
|
|
cover,
|
|
).SetAttribute("NGAP", "2"),
|
|
iup.Space().SetAttribute("SIZE", "x5"),
|
|
iup.Vbox(
|
|
convert,
|
|
),
|
|
iup.Fill(),
|
|
iup.Vbox(
|
|
iup.Label(i18n.Lng(i18n.LblProfile)),
|
|
profile,
|
|
reset,
|
|
save,
|
|
command,
|
|
).SetAttribute("NGAP", "2"),
|
|
).SetHandle("Buttons").SetAttributes("ALIGNMENT=ACENTER")
|
|
}
|
|
|
|
func status() iup.Ihandle {
|
|
return iup.Hbox(
|
|
loading(),
|
|
pageBox(),
|
|
iup.Fill(),
|
|
iup.Label("File 1 of 1").SetHandle("LabelStatus1").SetAttributes("VISIBLE=NO"),
|
|
iup.Space().SetAttribute("SIZE", "5"),
|
|
iup.Label("(000/000)").SetHandle("LabelStatus2").SetAttributes("VISIBLE=NO"),
|
|
iup.Space().SetAttribute("SIZE", "5"),
|
|
iup.ProgressBar().SetAttributes("VISIBLE=NO").SetHandle("ProgressBar").
|
|
SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int {
|
|
switch s {
|
|
case "convert":
|
|
conv := p.(*cbconvert.Converter)
|
|
ih.SetAttributes("VALUE=0, VISIBLE=YES")
|
|
ih.SetAttribute("MAX", conv.Ncontents)
|
|
|
|
iup.GetHandle("LabelStatus1").SetAttribute("TITLE", fmt.Sprintf(i18n.Str(i18n.StatusFileOf), conv.CurrFile, conv.Nfiles))
|
|
iup.GetHandle("LabelStatus1").SetAttributes("VISIBLE=YES")
|
|
iup.GetHandle("LabelStatus2").SetAttributes("VISIBLE=YES")
|
|
|
|
iup.Refresh(iup.GetHandle("StatusBar"))
|
|
case "start":
|
|
conv := p.(*cbconvert.Converter)
|
|
ih.SetAttributes("VALUE=0, VISIBLE=YES")
|
|
ih.SetAttribute("MAX", conv.Nfiles)
|
|
|
|
iup.GetHandle("LabelStatus2").SetAttributes("VISIBLE=YES")
|
|
case "progress":
|
|
conv := p.(*cbconvert.Converter)
|
|
ih.SetAttribute("VALUE", conv.CurrContent)
|
|
iup.GetHandle("LabelStatus2").SetAttribute("TITLE", fmt.Sprintf("(%03d/%03d)", conv.CurrContent, conv.Ncontents))
|
|
|
|
iup.Refresh(iup.GetHandle("StatusBar"))
|
|
case "progress2":
|
|
conv := p.(*cbconvert.Converter)
|
|
ih.SetAttribute("VALUE", conv.CurrFile)
|
|
iup.GetHandle("LabelStatus2").SetAttribute("TITLE", fmt.Sprintf("(%03d/%03d)", conv.CurrFile, conv.Nfiles))
|
|
|
|
iup.Refresh(iup.GetHandle("StatusBar"))
|
|
case "finish":
|
|
setBusy(false)
|
|
|
|
iup.GetHandle("LabelStatus1").SetAttributes(`TITLE="", VISIBLE=NO`)
|
|
iup.GetHandle("LabelStatus2").SetAttributes(`TITLE="", VISIBLE=NO`)
|
|
ih.SetAttributes("VALUE=0, VISIBLE=NO")
|
|
|
|
iup.Refresh(iup.GetHandle("StatusBar"))
|
|
|
|
iup.GetHandle("dlg").SetCallback("K_ANY", nil)
|
|
iup.GetHandle("dlg").SetCallback("CLOSE_CB", nil)
|
|
}
|
|
|
|
return iup.DEFAULT
|
|
})),
|
|
iup.Space().SetAttribute("SIZE", "5x0"),
|
|
).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=5x5").SetHandle("StatusBar")
|
|
}
|
|
|
|
func loading() iup.Ihandle {
|
|
img, _ := gif.DecodeAll(bytes.NewReader(appLoading))
|
|
animation := iup.User()
|
|
|
|
for idx, i := range img.Image {
|
|
name := fmt.Sprintf("Loading%d", idx)
|
|
iup.ImageFromImage(i).SetHandle(name)
|
|
iup.Append(animation, iup.GetHandle(name))
|
|
}
|
|
|
|
return iup.AnimatedLabel(animation).SetAttributes("VISIBLE=NO").SetHandle("Loading")
|
|
}
|