Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Darkmode #506

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion acme.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"flag"
"fmt"
"github.com/rjkroege/edwood/theme"
"image"
"log"
"os"
Expand Down Expand Up @@ -31,6 +32,7 @@ var (
winsize = flag.String("W", "1024x768", "Window size and position as WidthxHeight[@X,Y]")
ncol = flag.Int("c", 2, "Number of columns at startup")
loadfile = flag.String("l", "", "Load state from file generated with Dump command")
darkMode = flag.Bool("v", false, "Enable dark (Vampira) mode colour scheme") // Added dark mode flag
)

func predrawInit() *dumpfile.Content {
Expand Down Expand Up @@ -76,6 +78,10 @@ func mainWithDisplay(g *globals, dump *dumpfile.Content, display draw.Display) {
if err := display.Attach(draw.Refnone); err != nil {
log.Fatalf("failed to attach to window %v\n", err)
}

// Apply the appropriate mode based on the flag
g.applyMode(display)

display.ScreenImage().Draw(display.ScreenImage().R(), display.White(), nil, image.Point{})

g.mousectl = display.InitMouse()
Expand Down Expand Up @@ -153,14 +159,17 @@ func mainWithDisplay(g *globals, dump *dumpfile.Content, display draw.Display) {

func main() {
dump := predrawInit()

// Make the display here in the wrapper to make it possible to provide a
// different display for testing.
// Create the display within the closure to ensure proper scope
draw.Main(func(dd *draw.Device) {
display, err := dd.NewDisplay(nil, *varfontflag, "edwood", *winsize)
if err != nil {
log.Fatalf("can't open display: %v\n", err)
}

// Set dark mode state in theme package with display
theme.SetDarkMode(*darkMode, display)
mainWithDisplay(global, dump, display)
})
}
Expand Down
13 changes: 11 additions & 2 deletions frame/draw.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"image"

"github.com/rjkroege/edwood/draw"
"github.com/rjkroege/edwood/theme"
)

func (f *frameimpl) drawtext(pt image.Point, text draw.Image, back draw.Image) {
Expand Down Expand Up @@ -214,11 +215,19 @@ func (f *frameimpl) tick(pt image.Point, ticked bool) {
r.Max.X = f.rect.Max.X
}

// Determine the correct tick color based on dark mode
var tickColor draw.Image
if theme.IsDarkMode() {
tickColor = theme.TickColor // Use white tick for dark mode
} else {
tickColor = f.display.Black() // Use black tick for light mode
}

if ticked {
f.tickback.Draw(f.tickback.R(), f.background, nil, pt)
f.background.Draw(r, f.display.Black(), f.tickimage, image.Point{}) // draws an alpha-blended box
f.background.Draw(r, tickColor, f.tickimage, image.Point{}) // draws an alpha-blended box
} else {
// There is an issue with tick management
// Restore the background when removing the tick
f.background.Draw(r, f.tickback, nil, image.Point{})
}
f.ticked = ticked
Expand Down
35 changes: 31 additions & 4 deletions frame/tick.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package frame

import (
"image"

"github.com/rjkroege/edwood/draw"
"github.com/rjkroege/edwood/theme"
"image"
"log"
)

// InitTick sets up the TickImage (e.g. cursor)
// drawTick is a centralised function to render a tick with consistent logic.
func (f *frameimpl) drawTick(target draw.Image, tickColor draw.Image, rect image.Rectangle) {
target.Draw(rect, tickColor, nil, image.Point{})
}

// InitTick initialises the tick with consistent dark mode logic.
// TODO(rjk): doesn't appear to need to be exposed publically.
func (f *frameimpl) InitTick() {
if f.cols[ColBack] == nil || f.display == nil {
return
}

// Scaling factor
f.tickscale = f.display.ScaleSize(1)
b := f.display.ScreenImage()
ft := f.font

// Free existing tickimage if any
if f.tickimage != nil {
f.tickimage.Free()
}
Expand All @@ -26,21 +34,40 @@ func (f *frameimpl) InitTick() {
var err error
f.tickimage, err = f.display.AllocImage(image.Rect(0, 0, f.tickscale*frtickw, height), b.Pix(), false, draw.Transparent)
if err != nil {
log.Printf("InitTick: Failed to allocate tickimage: %v\n", err)
return
}

f.tickback, err = f.display.AllocImage(f.tickimage.R(), b.Pix(), false, draw.White)
var backgroundColor draw.Color
if theme.IsDarkMode() {
backgroundColor = theme.BackgroundColor
} else {
backgroundColor = theme.White
}

f.tickback, err = f.display.AllocImage(f.tickimage.R(), b.Pix(), false, backgroundColor)
if err != nil {
log.Printf("InitTick: Failed to allocate tickback image: %v\n", err)
f.tickimage.Free()
f.tickimage = nil
return
}

// Draw the background of the tick
f.tickback.Draw(f.tickback.R(), f.cols[ColBack], nil, image.Point{})

// Clear the tick image with transparency
f.tickimage.Draw(f.tickimage.R(), f.display.Transparent(), nil, image.Pt(0, 0))
// vertical line
f.tickimage.Draw(image.Rect(f.tickscale*(frtickw/2), 0, f.tickscale*(frtickw/2+1), height), f.display.Opaque(), nil, image.Pt(0, 0))
// box on each end
f.tickimage.Draw(image.Rect(0, 0, f.tickscale*frtickw, f.tickscale*frtickw), f.display.Opaque(), nil, image.Pt(0, 0))
f.tickimage.Draw(image.Rect(0, height-f.tickscale*frtickw, f.tickscale*frtickw, height), f.display.Opaque(), nil, image.Pt(0, 0))

// Flush the display buffer to ensure it's drawn
err = f.display.Flush()
if err != nil {
log.Printf("InitTick: Failed to flush display: %v\n", err)
f.tickimage = nil // Disable the tick functionality to avoid issues
}
}
54 changes: 51 additions & 3 deletions globals.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"9fans.net/go/plumb"
"github.com/rjkroege/edwood/draw"
"github.com/rjkroege/edwood/frame"
"github.com/rjkroege/edwood/theme"
)

// TODO(rjk): Document what each of these are.
Expand Down Expand Up @@ -154,12 +155,59 @@ func (g *globals) iconinit(display draw.Display) {
r.Max.X -= display.ScaleSize(ButtonBorder)
g.modbutton.Border(r, display.ScaleSize(ButtonBorder), g.tagcolors[frame.ColBord], image.Point{})
r = r.Inset(display.ScaleSize(ButtonBorder))
tmp, _ := display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, draw.Medblue)
g.modbutton.Draw(r, tmp, nil, image.Point{})
if *darkMode {
tmp, _ := display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, theme.ModButton)
g.modbutton.Draw(r, tmp, nil, image.Point{})
} else {
tmp, _ := display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, draw.Medblue)
g.modbutton.Draw(r, tmp, nil, image.Point{})
}

r = g.button.R()
g.colbutton, _ = display.AllocImage(r, display.ScreenImage().Pix(), false, draw.Purpleblue)
if *darkMode {
g.colbutton, _ = display.AllocImage(r, display.ScreenImage().Pix(), false, theme.ColButton)
} else {
g.colbutton, _ = display.AllocImage(r, display.ScreenImage().Pix(), false, draw.Purpleblue)
}

// These are the highlight colors for mouse buttons 2 and 3 functions
g.but2col, _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, 0xAA0000FF)
g.but3col, _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, 0x006600FF)
}

func (g *globals) applyMode(display draw.Display) {
if *darkMode {
// Apply dark mode colours
g.tagcolors[frame.ColBack], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, theme.TagColBack)
g.tagcolors[frame.ColHigh], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, theme.TagColHigh)
g.tagcolors[frame.ColBord], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, theme.TagColBord)
g.tagcolors[frame.ColText] = display.White()
g.tagcolors[frame.ColHText] = display.White()

g.textcolors[frame.ColBack], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, theme.TextColBack)
g.textcolors[frame.ColHigh], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, theme.TextColHigh)
g.textcolors[frame.ColText] = display.White()
g.textcolors[frame.ColHText] = display.White()

r := image.Rect(0, 0, display.ScaleSize(Scrollwid+ButtonBorder), fontget(g.tagfont, display).Height()+1)
g.colbutton, _ = display.AllocImage(r, display.ScreenImage().Pix(), false, 0xAA0000FF)

// These are the highlight colors for mouse buttons 2 and 3 functions
g.but2col, _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, 0xAA0000FF)
g.but3col, _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, 0x006600FF)

} else {
// Apply light mode colours (default)
g.tagcolors[frame.ColBack] = display.AllocImageMix(draw.Palebluegreen, draw.White)
g.tagcolors[frame.ColHigh], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, draw.Palegreygreen)
g.tagcolors[frame.ColBord], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, draw.Purpleblue)
g.tagcolors[frame.ColText] = display.Black()
g.tagcolors[frame.ColHText] = display.Black()

g.textcolors[frame.ColBack] = display.AllocImageMix(draw.Paleyellow, draw.White)
g.textcolors[frame.ColHigh], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, draw.Darkyellow)
g.textcolors[frame.ColBord], _ = display.AllocImage(image.Rect(0, 0, 1, 1), display.ScreenImage().Pix(), true, draw.Yellowgreen)
g.textcolors[frame.ColText] = display.Black()
g.textcolors[frame.ColHText] = display.Black()
}
}
159 changes: 159 additions & 0 deletions theme/theme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package theme

import (
"github.com/rjkroege/edwood/draw"
"image"
)

var darkMode bool

// SetDarkMode sets the dark mode state and applies the appropriate colors
func SetDarkMode(enabled bool, display draw.Display) {
darkMode = enabled
SetColorsForMode(darkMode, display)
}

// IsDarkMode returns the current dark mode state
func IsDarkMode() bool {
return darkMode
}

var (
Black draw.Color
Darkyellow draw.Color
Medblue draw.Color
Nofill draw.Color
Notacolor draw.Color
Opaque draw.Color
Palebluegreen draw.Color
Palegreygreen draw.Color
Paleyellow draw.Color
Purpleblue draw.Color
Transparent draw.Color
White draw.Color
Yellowgreen draw.Color

BackgroundColor draw.Color

TickColor draw.Image // Now this is not a pointer but an interface
TagColBack draw.Color
TagColHigh draw.Color

TagColBord draw.Color
TagColText draw.Color
TagHText draw.Color

TextColBack draw.Color // The text backgrounds
TextColHigh draw.Color // The text highlight
TextColBord draw.Color // The scroll bar background borders
TextColText draw.Color // The text
TextColHText draw.Color // The color of the text when highlighted

ModButton draw.Color
ColButton draw.Color

ButtonColor draw.Color
But2Col draw.Color
But3Col draw.Color

KeyCmd rune = draw.KeyCmd
KeyDown rune = draw.KeyDown
KeyEnd rune = draw.KeyEnd
KeyHome rune = draw.KeyHome
KeyInsert rune = draw.KeyInsert
KeyLeft rune = draw.KeyLeft
KeyPageDown rune = draw.KeyPageDown
KeyPageUp rune = draw.KeyPageUp
KeyRight rune = draw.KeyRight
KeyUp rune = draw.KeyUp
)

// SetColorsForMode sets colors based on the mode (dark or light)
func SetColorsForMode(isDarkMode bool, display draw.Display) {
if isDarkMode {
// Define colors for dark mode
Black = draw.Black
Darkyellow = 0x6665A8FF
Medblue = 0xFFFF6DFF
Nofill = draw.Nofill
Notacolor = draw.Notacolor
Palebluegreen = 0x110100FF
Palegreygreen = draw.Palegreygreen
Paleyellow = 0x000013FF
Purpleblue = 0x777738FF
Transparent = draw.Transparent
White = draw.White
Yellowgreen = 0x6665A8FF

TagColBack = 0x333333FF // The tagcolumn background
TagColHigh = 0x888888FF // The tagcolumn highlight

TagColBord = 0x888888FF // The tagcolumn border
TagColText = 0xEEEEEEFF // The tagcolumn text
TagHText = 0xEEEEEEFF // The tagcolumn text when highlighted

TextColBack = 0x222222FF // The text backgrounds
TextColHigh = 0x444444FF // The text highlight
TextColBord = 0x888888FF // The scroll bar background borders
TextColText = 0xEEEEEEFF // The text
TextColHText = 0xEEEEEEFF // The color of the text when highlighted

BackgroundColor = draw.Black

ModButton = 0x666666FF // The color of the file-modified button
ColButton = 0x666666FF // The color of the file-colour button

ButtonColor = draw.White // The color of the mouse buttons
But2Col = 0xAA0000FF // The color of the mouse button 2 functions
But3Col = 0x006600FF // The color of the mouse button 3 functions
} else {
// Define colors for light mode (default)
Darkyellow = draw.Darkyellow
Medblue = draw.Medblue
Nofill = draw.Nofill
Notacolor = draw.Notacolor
Palebluegreen = draw.Palebluegreen
Palegreygreen = draw.Palegreygreen
Paleyellow = draw.Paleyellow
Purpleblue = draw.Purpleblue
Transparent = draw.Transparent
White = draw.White
Yellowgreen = draw.Yellowgreen
Black = draw.Black

TagColBack = 0xE0E0E0FF // The tagcolumn background
TagColHigh = 0xC0C0C0FF // The tagcolumn highlight

TagColBord = 0x888888FF // The tagcolumn border
TagColText = draw.Black // The tagcolumn text
TagHText = draw.Black // The tagcolumn text when highlighted

TextColBack = 0xFFFFFFFF // The text backgrounds
TextColHigh = 0xFFFF00FF // The text highlight
TextColBord = 0x888888FF // The scroll bar background borders
TextColText = draw.Black // The text
TextColHText = draw.Black // The color of the text when highlighted

ModButton = 0x222222FF // The color of the file-modified button
ColButton = 0x666666FF // The color of the file-colour button

ButtonColor = draw.Black // The color of the mouse buttons
But2Col = 0xAA0000FF // The color of the mouse button 2 functions
But3Col = 0x006600FF // The color of the mouse button 3 functions
}

// Access the ScreenImage method and AllocImage method directly
screenImage := display.ScreenImage() // This calls the method on the Display interface

// Allocate an Image for TickColor based on the mode
var err error
if isDarkMode {
TickColor, err = display.AllocImage(image.Rect(0, 0, 1, 1), screenImage.Pix(), true, draw.White)
} else {
TickColor, err = display.AllocImage(image.Rect(0, 0, 1, 1), screenImage.Pix(), true, draw.Palegreygreen)
}

if err != nil {
panic("Failed to allocate TickColor image: " + err.Error())
}
}