eumandy/eugtk/GtkSettings.e
2016-11-25 00:27:22 -07:00

306 lines
7.5 KiB
Plaintext

---------------------
namespace settings -- functions to read and write config files (*.ini);
---------------------
export constant version = "4.12.0"
--# EXPORTS
/*
--functions:
settings:Save()
settings:Load()
settings:Add()
-- debug:
-d SETTINGS
*/
include GtkEngine.e
if not equal(version,gtk:version) then
Error(,,"GtkSettings version mismatch","should be version " & gtk:version)
end if
constant fmt = """[].[]=[]"""
------------------------------------------------------------------------
export function Save(sequence inifile, object ctl_list, integer debug=0)
------------------------------------------------------------------------
-- writes an 'ini' type file (file name and extension are up to you)
-- with an entry for each control on ctl_list. The controls MUST have
-- been named, otherwise there's no way to save and retrieve the
-- value/setting for that control.
------------------------------------------------------------------------
object comments = {}
object txt,line
if file_exists(inifile) then
txt = read_lines(inifile)
for i = 1 to length(txt) do -- extract the comments;
line = txt[i]
if match("--",line) = 1
or match("!",line) = 1
or match("+",line) = 1
or equal("\n",line)
or equal({},line) then
comments = append(comments,line)
end if
end for
write_lines(inifile,comments) -- removing everything but the comments;
end if -- file exists
object setting, tmp = 0, pos = {0,0}
object t1, name, prop
atom handle
integer class
atom fn = open(inifile,"a")
for x = 1 to length(ctl_list) do
if string(ctl_list[x]) then
handle = pointer(ctl_list[x])
else
handle = ctl_list[x]
end if
name = get(handle,"name")
class = class_id(handle)
if class=GtkWindow then -- special handling for multiple properties;
printf(fn,"%s\n",{get_setting(handle,"size")})
pos = get(handle,"position")
printf(fn,"%s.position={%d,%d}\n",{name,pos[1],pos[2]})
else
setting = get_setting(handle) -- others have 1 obvious 'saveable' property
if length(setting) < 1 then
continue
end if
if sequence(setting) then
printf(fn,"%s\n",{setting})
end if
end if
end for
flush(fn)
close(fn)
-- if ! exists for this control:property, then ignore the updated setting;
tmp = read_lines(inifile)
for i = 1 to length(tmp) do
if match("--!",tmp[i]) = 1 then
t1 = split(tmp[i],"=")
t1 = t1[1][2..$]
end if
end for
write_lines(inifile,tmp)
return 1
end function
------------------------------------------------------------------------
export function Load(sequence inifile, integer debug=0)
------------------------------------------------------------------------
-- used to restore settings from the specified ini file.
-- this should be called after the controls are 'realized'
object txt, line, obj, prop, val1=0, val2=0, val3=0, val4=0
if not(file_exists(inifile)) then
write_file(inifile,sprintf("--%s\n\n",{inifile}),TEXT_MODE)
display("Creating ini file: []",{inifile})
else
if debug then display("Reading []",{inifile}) end if
end if
txt = read_lines(inifile)
integer err=0
object a,b
for i = 1 to length(txt) do
line = txt[i]
if match("--",line) > 2 then -- strip trailing comments;
line = line[1..match("--",line)-2]
end if
if match("--!",line) = 1 then
line = line[4..$] -- keep it
end if
if match("+",line) = 1 or match("!",line) then
line = line[2..$] -- dito
end if
if match("--",line) or match(";",line)
or match("/*",line) then
continue -- a comment, do nothing with it
end if
if length(line) > 0 then
line = split(line,'=')
a = line[1] b = line[2]
a = split(a,'.')
line = a & {b}
if debug > 1 then display(line) end if
if vlookup(line[1],registry,4,1,-1) = -1 then
err = i
Error(,"Ini Load Error",
sprintf("Invalid object name: %s",{line[1]}),
sprintf("Line #%d of %s",{i,filename(inifile)}))
else
if equal("data",line[2]) then
set(line[1],"data",line[3],line[4])
else
set(line[1],line[2],line[3])
end if
end if
end if
end for
if debug = 1 then
for i = 1 to length(txt) do
if i = err then
display("ERROR:[:3]:[]",{i,txt[i]})
else
display("[:3]:[]",{i,txt[i]})
end if
end for
end if
write_lines(inifile,txt)
return 1
end function
-------------------------------------------------------------------------------------------
export function Add(object ini,object ctl, sequence prop, object v1=0, object v2=0)
-------------------------------------------------------------------------------------------
if atom(ctl) then ctl = get(ctl,"name") end if
Delete(ini,ctl,prop)
if equal("position",prop) or equal("size",prop) then
if string(v1) then v2 = v1[2] v1 = v1[1] end if
end if
if atom(v2) and v2=0 then
writefln("+[].[]=[]",{ctl,prop,v1},{ini,"a"})
else
writefln("+[].[]={[],[]}",{ctl,prop,v1,v2},{ini,"a"})
end if
return 1
end function
--------------------------------------------------------------------
export function Delete(object ini,object ctl, sequence prop)
--------------------------------------------------------------------
if atom(ctl) then ctl = get(ctl,"name") end if
object tmp = read_lines(ini)
object out = {}
object s1 = text:format("[].[]",{ctl,prop})
for i = 1 to length(tmp) do
if match(s1,tmp[i]) then -- skip
else out &= {tmp[i]}
end if
end for
write_lines(ini,out)
return 1
end function
---------------------------------------------------------------------------------
function get_setting(object self, object property = 0)
-- returns the 'important' value from a control
---------------------------------------------------------------------------------
-- returns settings string
-- object must be a named object, e.g. MyButton
-- MyButton.active=1
-- My Calendar.date={YYYY,MM,DD}
object name = 0
object dt
if string(self) then
name = self
self = vlookup(self,registry,4,1)
end if
object val = 0
object txt = {}
integer x = find(self,vslice(registry,1))
ifdef SETTINGS then
display("SELF [] []",{x,self})
display(registry[x])
end ifdef
switch class_id(self) do
-- this decides which value is the important one to save;
-- and stores the control's current value into the registry;
case GtkEntry,GtkEntryBuffer then property = "text"
case GtkCheckButton,GtkRadioButton, GtkToggleButton,
GtkSwitch,GtkComboBox,GtkComboBoxText,
GtkCheckMenuItem,GtkToggleToolButton, GtkSearchEntry
then property = "active"
case GtkPopover then property = "position"
case GtkFontButton then property = "font name"
case GtkAdjustment,GtkSpinButton,GtkScaleButton,GtkVolumeButton,
GtkModelButton,GtkScale
then property = "value"
case GtkEntryCompletion then property = "model"
case GtkLinkButton then property = "uri"
case GtkMenuItem then property = "sensitive"
case GtkPaned then property = "position"
case GtkFileChooser, GtkFileChooserButton, GtkFileChooserWidget, GtkFileChooserDialog
then property = "filename"
case GtkFontChooser, GtkFontChooserWidget, GtkFontChooserDialog then
property = "font"
case GtkCalendar then
dt = get(self,"datetime",0)
registry[x][5] = {"date",dt[1..3]}
txt &= text:format(fmt,{registry[x][4],"date",dt[1..3]})
return txt
case GtkColorButton,GtkColorChooser,GtkColorChooserWidget,
GtkColorChooserDialog then
registry[x][5] = {"rgba",get(self,"rgba",1)}
txt &= text:format(fmt,{registry[x][4],"rgba",get(self,"rgba",1)})
return txt
end switch
if atom(property) then
return txt
end if
val = get(self,property)
registry[x][5] = {property,val}
txt &= text:format(fmt,{registry[x][4],property,val})
return txt
end function