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.*
|
||||
*.so
|
||||
.vscode
|
107
scripting.py
107
scripting.py
|
@ -54,8 +54,7 @@ class Defs(TPrs):
|
|||
|
||||
class Vm(TPrs):
|
||||
def InitPersistent(self, defs):
|
||||
self.rgflagdef = defs.rgflagdef
|
||||
self.rgbotdef = defs.rgbotdef
|
||||
self.defs = defs
|
||||
self.mpflagdef = { flagdef: flagdef.value for flagdef in defs.rgflagdef }
|
||||
self.mpbotdef = { botdef: Rbot(botdef) for botdef in defs.rgbotdef }
|
||||
def SetFlag(self, flagdef, fValue):
|
||||
|
@ -147,24 +146,45 @@ class Synt(Typeable):
|
|||
def SyntDefault(cls):
|
||||
return cls()
|
||||
|
||||
def ProjectTypein(self, pcur):
|
||||
return self.syntParent.ProjectTypeinForChild(pcur.defs, pcur.PwHoriz(self), self, self.StForTypein())
|
||||
def Populate(self):
|
||||
"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):
|
||||
self.Replace(syntChild, synt)
|
||||
syntChild.SetStTypein(None)
|
||||
if syntChild.GetStTypein() != None:
|
||||
pwParent = PwDropdown(pwParent)
|
||||
PwTypein(pwParent, st, syntChild)
|
||||
if syntChild.GetStTypein() != None:
|
||||
pwTypein = PwTypein(pwParent, st, syntChild)
|
||||
stype = self.StypeForChild(syntChild)
|
||||
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)
|
||||
|
||||
def StypeForChild(self, syntChild):
|
||||
return None
|
||||
pcur.pwTooltip.AddTip(pwParent, Tooltip)
|
||||
else:
|
||||
pcur.pwTooltip.AddTip(pwTypein, Tooltip)
|
||||
|
||||
def Replace(self, syntOld, syntNew):
|
||||
assert syntNew.syntParent == None
|
||||
|
@ -181,16 +201,9 @@ class Synt(Typeable):
|
|||
return syntChild
|
||||
return self.rgsynt.index(syntChild)
|
||||
|
||||
def Populate(self):
|
||||
"Populate rgsynt with useful default values."
|
||||
pass
|
||||
def Stype(self):
|
||||
return self.syntParent.stypeForChild(self) if self.syntParent else None
|
||||
|
||||
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
|
||||
# desce:
|
||||
|
@ -283,8 +296,6 @@ class SyntBlock(Synt):
|
|||
def Project(self, pcur):
|
||||
with pcur.Indent(2 if pcur.pwHoriz != None else 0):
|
||||
pcur.EndLine()
|
||||
if pcur.pwVert == None:
|
||||
pcur.pwVert = PwBlock(None, self, pcur.dxindent)
|
||||
def OnInsertNewLine(syntAfter, psel):
|
||||
self.InsertLineAfter(syntAfter, None)
|
||||
psel.Inc(pcur.pwVert) # does nothing because we need to reproject
|
||||
|
@ -420,14 +431,16 @@ class Fail(TPrs):
|
|||
class Pcur(object):
|
||||
@staticmethod
|
||||
def PwProjected(defs, synt):
|
||||
pcur = Pcur(defs)
|
||||
pcur = Pcur(defs, synt)
|
||||
synt.Project(pcur)
|
||||
return pcur.pwVert
|
||||
return pcur.pwSplit
|
||||
|
||||
def __init__(self, defs):
|
||||
def __init__(self, defs, synt):
|
||||
self.defs = defs
|
||||
self.pwVert = None
|
||||
self.pwSplit = PwSplit(None, 80)
|
||||
self.pwVert = PwBlock(self.pwSplit, synt, 0)
|
||||
self.pwHoriz = None
|
||||
self.pwTooltip = PwTooltip(self.pwSplit)
|
||||
self.dxindent = 0
|
||||
|
||||
@contextmanager
|
||||
|
@ -520,6 +533,35 @@ class PwExpand(PwContainOne):
|
|||
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)
|
||||
|
||||
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):
|
||||
def __init__(self, pwParent, stText):
|
||||
Pw.__init__(self, pwParent)
|
||||
|
@ -681,6 +723,11 @@ class PwDropdown(PwBlock):
|
|||
return PwBlock.RgpwChild(self)[0]
|
||||
def DxDyNew(self, 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):
|
||||
if not fOverlay:
|
||||
self.PwChildFirst().Draw(ascr, x, y, w, dxStart, mpksel, False)
|
||||
|
@ -866,16 +913,22 @@ class PselState(LeaveJoinToken):
|
|||
class Mpksel(object):
|
||||
def __init__(self, pwRoot, client, mpclient_psel):
|
||||
self.mppw_ksel = {}
|
||||
self.pwNav = None
|
||||
for clientT, psel in mpclient_psel.items():
|
||||
kselNew = Ksel.NAV
|
||||
pw = psel.PwSelected(pwRoot)
|
||||
if clientT != client:
|
||||
kselNew = kselNew | Ksel.FOTHER
|
||||
pw = psel.PwSelected(pwRoot)
|
||||
else:
|
||||
self.pwNav = pw
|
||||
self.mppw_ksel[pw] = Ksel.KselBest(kselNew, self.Get(pw))
|
||||
|
||||
def Get(self, pw):
|
||||
return self.mppw_ksel.get(pw, Ksel.NONE)
|
||||
|
||||
def GetPwNav(self):
|
||||
return self.pwNav
|
||||
|
||||
def GetMpksel(self, pwRoot, client):
|
||||
return self.Mpksel(pwRoot, client, self.mpclient_psel)
|
||||
def PselByClient(self, client):
|
||||
|
|
Loading…
Reference in a new issue