Add tooltip sidebar, auto-select first item in dropdown with enter
This commit is contained in:
parent
4e720f0d67
commit
f7c33a23a6
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@ build
|
||||||
*.marm
|
*.marm
|
||||||
*.marm.*
|
*.marm.*
|
||||||
*.so
|
*.so
|
||||||
|
.vscode
|
107
scripting.py
107
scripting.py
|
@ -54,8 +54,7 @@ class Defs(TPrs):
|
||||||
|
|
||||||
class Vm(TPrs):
|
class Vm(TPrs):
|
||||||
def InitPersistent(self, defs):
|
def InitPersistent(self, defs):
|
||||||
self.rgflagdef = defs.rgflagdef
|
self.defs = defs
|
||||||
self.rgbotdef = defs.rgbotdef
|
|
||||||
self.mpflagdef = { flagdef: flagdef.value for flagdef in defs.rgflagdef }
|
self.mpflagdef = { flagdef: flagdef.value for flagdef in defs.rgflagdef }
|
||||||
self.mpbotdef = { botdef: Rbot(botdef) for botdef in defs.rgbotdef }
|
self.mpbotdef = { botdef: Rbot(botdef) for botdef in defs.rgbotdef }
|
||||||
def SetFlag(self, flagdef, fValue):
|
def SetFlag(self, flagdef, fValue):
|
||||||
|
@ -147,24 +146,45 @@ class Synt(Typeable):
|
||||||
def SyntDefault(cls):
|
def SyntDefault(cls):
|
||||||
return cls()
|
return cls()
|
||||||
|
|
||||||
def ProjectTypein(self, pcur):
|
def Populate(self):
|
||||||
return self.syntParent.ProjectTypeinForChild(pcur.defs, pcur.PwHoriz(self), self, self.StForTypein())
|
"Populate rgsynt with useful default values."
|
||||||
|
pass
|
||||||
|
|
||||||
def ProjectTypeinForChild(self, defs, pwParent, syntChild, st):
|
def Project(self, pcur):
|
||||||
|
"Project the current synt into its corresponding pws."
|
||||||
|
pass
|
||||||
|
def Eval(self, vm):
|
||||||
|
"Execute yourself, in the context of vm."
|
||||||
|
return Fail("Missing information", self)
|
||||||
|
|
||||||
|
def StypeForChild(self, syntChild):
|
||||||
|
"Return the stype that should be applied to the given child."
|
||||||
|
return None
|
||||||
|
|
||||||
|
def ProjectTypein(self, pcur):
|
||||||
|
return self.syntParent.ProjectTypeinForChild(pcur, self, self.StForTypein())
|
||||||
|
|
||||||
|
def ProjectTypeinForChild(self, pcur, syntChild, st):
|
||||||
|
pwParent = pcur.PwHoriz(syntChild)
|
||||||
def OnSelect(synt, psel):
|
def OnSelect(synt, psel):
|
||||||
self.Replace(syntChild, synt)
|
self.Replace(syntChild, synt)
|
||||||
syntChild.SetStTypein(None)
|
syntChild.SetStTypein(None)
|
||||||
if syntChild.GetStTypein() != None:
|
if syntChild.GetStTypein() != None:
|
||||||
pwParent = PwDropdown(pwParent)
|
pwParent = PwDropdown(pwParent)
|
||||||
PwTypein(pwParent, st, syntChild)
|
pwTypein = PwTypein(pwParent, st, syntChild)
|
||||||
if syntChild.GetStTypein() != None:
|
|
||||||
stype = self.StypeForChild(syntChild)
|
stype = self.StypeForChild(syntChild)
|
||||||
if stype:
|
if stype:
|
||||||
for synt in stype.RgsyntFromSt(defs, syntChild.GetStTypein()):
|
def Tooltip():
|
||||||
|
pw = PwBlock(None, None, 0)
|
||||||
|
for synt in stype.RgsyntFromSt(pcur.defs, ''):
|
||||||
|
PwStatic(pw, synt.StForTypein())
|
||||||
|
return pw
|
||||||
|
if syntChild.GetStTypein() != None:
|
||||||
|
for synt in stype.RgsyntFromSt(pcur.defs, syntChild.GetStTypein()):
|
||||||
PwButton(pwParent, synt.StForTypein(), synt, OnSelect)
|
PwButton(pwParent, synt.StForTypein(), synt, OnSelect)
|
||||||
|
pcur.pwTooltip.AddTip(pwParent, Tooltip)
|
||||||
def StypeForChild(self, syntChild):
|
else:
|
||||||
return None
|
pcur.pwTooltip.AddTip(pwTypein, Tooltip)
|
||||||
|
|
||||||
def Replace(self, syntOld, syntNew):
|
def Replace(self, syntOld, syntNew):
|
||||||
assert syntNew.syntParent == None
|
assert syntNew.syntParent == None
|
||||||
|
@ -181,16 +201,9 @@ class Synt(Typeable):
|
||||||
return syntChild
|
return syntChild
|
||||||
return self.rgsynt.index(syntChild)
|
return self.rgsynt.index(syntChild)
|
||||||
|
|
||||||
def Populate(self):
|
def Stype(self):
|
||||||
"Populate rgsynt with useful default values."
|
return self.syntParent.stypeForChild(self) if self.syntParent else None
|
||||||
pass
|
|
||||||
|
|
||||||
def Project(self, pcur):
|
|
||||||
"Project the current synt into its corresponding pws."
|
|
||||||
pass
|
|
||||||
def Eval(self, vm):
|
|
||||||
"Execute yourself, in the context of vm."
|
|
||||||
return Fail("Missing information", self)
|
|
||||||
|
|
||||||
# desc - list of desces
|
# desc - list of desces
|
||||||
# desce:
|
# desce:
|
||||||
|
@ -283,8 +296,6 @@ class SyntBlock(Synt):
|
||||||
def Project(self, pcur):
|
def Project(self, pcur):
|
||||||
with pcur.Indent(2 if pcur.pwHoriz != None else 0):
|
with pcur.Indent(2 if pcur.pwHoriz != None else 0):
|
||||||
pcur.EndLine()
|
pcur.EndLine()
|
||||||
if pcur.pwVert == None:
|
|
||||||
pcur.pwVert = PwBlock(None, self, pcur.dxindent)
|
|
||||||
def OnInsertNewLine(syntAfter, psel):
|
def OnInsertNewLine(syntAfter, psel):
|
||||||
self.InsertLineAfter(syntAfter, None)
|
self.InsertLineAfter(syntAfter, None)
|
||||||
psel.Inc(pcur.pwVert) # does nothing because we need to reproject
|
psel.Inc(pcur.pwVert) # does nothing because we need to reproject
|
||||||
|
@ -420,14 +431,16 @@ class Fail(TPrs):
|
||||||
class Pcur(object):
|
class Pcur(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def PwProjected(defs, synt):
|
def PwProjected(defs, synt):
|
||||||
pcur = Pcur(defs)
|
pcur = Pcur(defs, synt)
|
||||||
synt.Project(pcur)
|
synt.Project(pcur)
|
||||||
return pcur.pwVert
|
return pcur.pwSplit
|
||||||
|
|
||||||
def __init__(self, defs):
|
def __init__(self, defs, synt):
|
||||||
self.defs = defs
|
self.defs = defs
|
||||||
self.pwVert = None
|
self.pwSplit = PwSplit(None, 80)
|
||||||
|
self.pwVert = PwBlock(self.pwSplit, synt, 0)
|
||||||
self.pwHoriz = None
|
self.pwHoriz = None
|
||||||
|
self.pwTooltip = PwTooltip(self.pwSplit)
|
||||||
self.dxindent = 0
|
self.dxindent = 0
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
@ -520,6 +533,35 @@ class PwExpand(PwContainOne):
|
||||||
ascr.PutSt(" " * w, x, y, self.pwChild.ColFg(), self.pwChild.ColBg(mpksel.Get(self.pwChild)))
|
ascr.PutSt(" " * w, x, y, self.pwChild.ColFg(), self.pwChild.ColBg(mpksel.Get(self.pwChild)))
|
||||||
self.pwChild.Draw(ascr, x, y, w, dxStart, mpksel, fOverlay)
|
self.pwChild.Draw(ascr, x, y, w, dxStart, mpksel, fOverlay)
|
||||||
|
|
||||||
|
class PwTooltip(Pw):
|
||||||
|
def __init__(self, pwParent):
|
||||||
|
Pw.__init__(self, pwParent)
|
||||||
|
self.mppw_tip = {}
|
||||||
|
def AddTip(self, pw, tip):
|
||||||
|
self.mppw_tip[pw] = tip
|
||||||
|
def Draw(self, ascr, x, y, w, dxStart, mpksel, fOverlay):
|
||||||
|
pwNav = mpksel.GetPwNav()
|
||||||
|
while pwNav:
|
||||||
|
tip = self.mppw_tip.get(pwNav)
|
||||||
|
if tip:
|
||||||
|
tip().Draw(ascr, x, y, w, dxStart, mpksel, fOverlay)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
pwNav = pwNav.pwParent
|
||||||
|
|
||||||
|
class PwSplit(PwContainer):
|
||||||
|
def __init__(self, pwParent, pctLeft):
|
||||||
|
PwContainer.__init__(self, pwParent)
|
||||||
|
self.pctLeft = pctLeft
|
||||||
|
def Draw(self, ascr, x, y, w, dxStart, mpksel, fOverlay):
|
||||||
|
assert len(self.RgpwChild()) == 2
|
||||||
|
wLeft = (self.pctLeft * w) / 100
|
||||||
|
wRight = w - wLeft - 1
|
||||||
|
self.RgpwChild()[0].Draw(ascr, x, y, wLeft, dxStart, mpksel, fOverlay)
|
||||||
|
self.RgpwChild()[1].Draw(ascr, x + wLeft + 1, y, wRight, 0, mpksel, fOverlay)
|
||||||
|
if not fOverlay:
|
||||||
|
ascr.Fill(ansi.MkAch(chr(186), ansi.WHITE | ansi.FBRIGHT, ansi.BLACK), 1, ascr.H() - y + 1, x + wLeft, y)
|
||||||
|
|
||||||
class PwStatic(Pw):
|
class PwStatic(Pw):
|
||||||
def __init__(self, pwParent, stText):
|
def __init__(self, pwParent, stText):
|
||||||
Pw.__init__(self, pwParent)
|
Pw.__init__(self, pwParent)
|
||||||
|
@ -681,6 +723,11 @@ class PwDropdown(PwBlock):
|
||||||
return PwBlock.RgpwChild(self)[0]
|
return PwBlock.RgpwChild(self)[0]
|
||||||
def DxDyNew(self, w, dxStart, mpksel):
|
def DxDyNew(self, w, dxStart, mpksel):
|
||||||
return self.PwChildFirst().DxDyNew(w, dxStart, mpksel)
|
return self.PwChildFirst().DxDyNew(w, dxStart, mpksel)
|
||||||
|
def HandleKey(self, pov, psel, key):
|
||||||
|
if (key == ansi.K_RETURN or key == ansi.K_NEWLINE) and len(self.RgpwChild()) > 1:
|
||||||
|
return self.RgpwChild()[1].HandleKey(pov, psel, key)
|
||||||
|
return PwBlock.HandleKey(self, pov, psel, key)
|
||||||
|
|
||||||
def Draw(self, ascr, x, y, w, dxStart, mpksel, fOverlay):
|
def Draw(self, ascr, x, y, w, dxStart, mpksel, fOverlay):
|
||||||
if not fOverlay:
|
if not fOverlay:
|
||||||
self.PwChildFirst().Draw(ascr, x, y, w, dxStart, mpksel, False)
|
self.PwChildFirst().Draw(ascr, x, y, w, dxStart, mpksel, False)
|
||||||
|
@ -866,16 +913,22 @@ class PselState(LeaveJoinToken):
|
||||||
class Mpksel(object):
|
class Mpksel(object):
|
||||||
def __init__(self, pwRoot, client, mpclient_psel):
|
def __init__(self, pwRoot, client, mpclient_psel):
|
||||||
self.mppw_ksel = {}
|
self.mppw_ksel = {}
|
||||||
|
self.pwNav = None
|
||||||
for clientT, psel in mpclient_psel.items():
|
for clientT, psel in mpclient_psel.items():
|
||||||
kselNew = Ksel.NAV
|
kselNew = Ksel.NAV
|
||||||
|
pw = psel.PwSelected(pwRoot)
|
||||||
if clientT != client:
|
if clientT != client:
|
||||||
kselNew = kselNew | Ksel.FOTHER
|
kselNew = kselNew | Ksel.FOTHER
|
||||||
pw = psel.PwSelected(pwRoot)
|
else:
|
||||||
|
self.pwNav = pw
|
||||||
self.mppw_ksel[pw] = Ksel.KselBest(kselNew, self.Get(pw))
|
self.mppw_ksel[pw] = Ksel.KselBest(kselNew, self.Get(pw))
|
||||||
|
|
||||||
def Get(self, pw):
|
def Get(self, pw):
|
||||||
return self.mppw_ksel.get(pw, Ksel.NONE)
|
return self.mppw_ksel.get(pw, Ksel.NONE)
|
||||||
|
|
||||||
|
def GetPwNav(self):
|
||||||
|
return self.pwNav
|
||||||
|
|
||||||
def GetMpksel(self, pwRoot, client):
|
def GetMpksel(self, pwRoot, client):
|
||||||
return self.Mpksel(pwRoot, client, self.mpclient_psel)
|
return self.Mpksel(pwRoot, client, self.mpclient_psel)
|
||||||
def PselByClient(self, client):
|
def PselByClient(self, client):
|
||||||
|
|
Loading…
Reference in a new issue