Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Commit

Permalink
Zwischenstand
Browse files Browse the repository at this point in the history
  • Loading branch information
janopae committed Apr 7, 2023
1 parent a422e15 commit bc5c718
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 48 deletions.
13 changes: 8 additions & 5 deletions src/trelby.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,23 +163,22 @@ def __init__(self, parent, id):
self, parent, id,
# wxMSW/Windows does not seem to support
# wx.NO_BORDER, which sucks
style = wx.WANTS_CHARS | wx.NO_BORDER | wx.HSCROLL)
style = wx.WANTS_CHARS | wx.NO_BORDER | wx.HSCROLL | wx.VSCROLL)

hsizer = wx.BoxSizer(wx.HORIZONTAL)

self.scrollBarVertical = wx.ScrollBar(self, -1, style = wx.SB_VERTICAL)
self.ctrl = MyCtrl(self, -1)

hsizer.Add(self.ctrl, 1, wx.EXPAND)
hsizer.Add(self.scrollBarVertical, 0, wx.EXPAND)

self.scrollBarVertical.Bind(wx.EVT_COMMAND_SCROLL, self.ctrl.OnScroll)

self.scrollBarVertical.Bind(wx.EVT_SET_FOCUS, self.OnScrollbarFocus)

self.SetSizer(hsizer)
self.SetScrollRate(int(self.ctrl.chX), int(self.ctrl.chY))
self.EnableScrolling(True, False)
self.EnableScrolling(True, True)

# we never want the scrollbar to get the keyboard focus, pass it on to
# the main widget
Expand All @@ -188,7 +187,7 @@ def OnScrollbarFocus(self, event):

class MyCtrl(wx.Control):

def __init__(self, parent, id):
def __init__(self, parent: MyPanel, id):
style = wx.WANTS_CHARS | wx.FULL_REPAINT_ON_RESIZE | wx.NO_BORDER
wx.Control.__init__(self, parent, id, style = style)

Expand Down Expand Up @@ -435,9 +434,13 @@ def isUntouched(self):
else:
return True

def getVisibleAreaSize(self):
''' Size of the area visble in the scrolled window'''
return self.panel.GetSize()

def updateScreen(self, redraw = True, setCommon = True):
self.adjustScrollBar()
self.SetMinSize(wx.Size(int(self.pageW), 10)) # the vertical min size is irrelevant currently, as vertical scrolling is still self-implemented
self.SetMinSize(wx.Size(int(self.pageW), gd.vm.getDocumentHeight(self)))
self.PostSizeEventToParent()

if setCommon:
Expand Down
131 changes: 88 additions & 43 deletions src/viewmode.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# -*- coding: iso-8859-1 -*-
import math
from typing import Optional

import config
import mypager
import pml
import screenplay
import trelby
import util

# Number of lines the smooth scroll will try to search. 15-20 is a good
Expand Down Expand Up @@ -82,6 +86,9 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):
def getLineHeight(self, ctrl):
raise Exception("getLineHeight not implemented")

def getDocumentHeight(self, ctrl, untilLine: Optional[int] = None) -> int:
raise Exception("getLineHeight not implemented")

# return width of one page in (floating point) pixels
def getPageWidth(self, ctrl):
raise Exception("getPageWidth not implemented")
Expand Down Expand Up @@ -147,6 +154,10 @@ def makeLineVisibleGeneric(self, ctrl, line, texts, direction, jumpAhead):

# helper function for makeLineVisibleGeneric
def _makeLineVisibleHelper(self, ctrl, line, direction, jumpAhead):
currentLine = ctrl.sp.line
linePosition = self.getDocumentHeight(ctrl, currentLine)


startLine = ctrl.sp.getTopLine()
sign = 1 if (direction == config.SCROLL_DOWN) else -1
i = 1
Expand Down Expand Up @@ -207,13 +218,13 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):

marginLeft = int(ctrl.mm2p * cfg.marginLeft)
cox = util.clamp((width - ctrl.pageW) // 2, 0)
fyd = ctrl.sp.cfgGl.fontYdelta
fyd = self.getLineHeight(ctrl)
length = len(ls)

texts = []

while (y < height) and (i < length):
y += int((ctrl.sp.getSpacingBefore(i) / 10.0) * fyd)
y += self.__getLineHeightWithSpacing(ctrl, i)

if y >= height:
break
Expand Down Expand Up @@ -245,6 +256,22 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):
def getLineHeight(self, ctrl):
return ctrl.sp.cfgGl.fontYdelta

def __getLineHeightWithSpacing(self, ctrl, lineNumber: int):
lineHeightWithoutSpacing = self.getLineHeight(ctrl)
return lineHeightWithoutSpacing + int((ctrl.sp.getSpacingBefore(lineNumber) / 10.0) * lineHeightWithoutSpacing)

def getDocumentHeight(self, ctrl, untilLine: Optional[int] = None) -> int:
if untilLine is None:
untilLine = len(ctrl.sp.lines)
height = 0
for i in range(untilLine):
height += self.__getLineHeightWithSpacing(ctrl, i)

height += ctrl.getVisibleAreaSize().GetHeight() # One should always be able to scroll at least until the last line is on top

return height


def getPageWidth(self, ctrl):
# this is not really used for much in draft mode, as it has no
# concept of page width, but it's safer to return something
Expand All @@ -264,7 +291,7 @@ def pageCmd(self, ctrl, cs, dir, texts, dpages):
# Layout view mode. Pages are shown with the actual layout they would
# have.
class ViewModeLayout(ViewMode):

PAGE_GAP = 10 # gap between pages (pixels)
def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):
cfgGui = ctrl.getCfgGui()
textOp = pml.TextOp
Expand All @@ -274,8 +301,6 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):

width, height = ctrl.GetClientSize()

# gap between pages (pixels)
pageGap = 10
pager = mypager.Pager(ctrl.sp.cfg)

mm2p = ctrl.mm2p
Expand Down Expand Up @@ -307,7 +332,7 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):
if not topOfPage:
y = -int(op.y * mm2p)
else:
y = pageGap
y = self.PAGE_GAP

break
else:
Expand Down Expand Up @@ -366,7 +391,7 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):
cfgGui.fonts[op.flags & 3],
op.flags & pml.UNDERLINED))

y = pageY + ctrl.pageH + pageGap
y = pageY + ctrl.pageH + self.PAGE_GAP
pg = None

# if user has inserted new text causing the script to overflow
Expand All @@ -385,6 +410,23 @@ def getLineHeight(self, ctrl):
# lines.
return int(ctrl.chY * ctrl.mm2p + 1.0)

def getDocumentHeight(self, ctrl, untilLine: Optional[int] = None) -> int:
'''
:type ctrl: trelby.MyCtrl
'''
if untilLine is None:
untilPage = len(ctrl.sp.pages)
else:
untilPage = ctrl.sp.line2page(untilLine) - 1

height = (untilPage - 1) * (ctrl.pageH + self.PAGE_GAP)
height += 2 * self.PAGE_GAP # gap on top and on the bottom

if untilLine is not None:
height += ctrl.chY * ctrl.mm2p # in case a specific line is requested, we need to be line exact

return height

def getPageWidth(self, ctrl):
return (ctrl.sp.cfg.paperWidth / ctrl.chX) *\
ctrl.getCfgGui().fonts[pml.NORMAL].fx
Expand All @@ -402,7 +444,7 @@ def pageCmd(self, ctrl, cs, dir, texts, dpages):
# would have, as many pages at a time as fit on the screen, complete pages
# only, in a single row.
class ViewModeSideBySide(ViewMode):

PAGE_GAP = 10 # gap between pages (+ screen left edge)
def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):
cfgGui = ctrl.getCfgGui()
textOp = pml.TextOp
Expand All @@ -414,64 +456,67 @@ def getScreen(self, ctrl, doExtra, partials = False, pageCache = None):

mm2p = ctrl.mm2p

# gap between pages (+ screen left edge)
pageGap = 10

# how many pages fit on screen
pageCnt = max(1, (width - pageGap) // (ctrl.pageW + pageGap))
pagesPerRow = max(1, (width - self.PAGE_GAP) // (ctrl.pageW + self.PAGE_GAP))

pager = mypager.Pager(ctrl.sp.cfg)

topLine = ctrl.sp.getTopLine()
pageNr = ctrl.sp.line2page(topLine)
pageNr = 1 # for now, we just render the whole document

if doExtra and ctrl.sp.cfg.pdfShowSceneNumbers:
pager.scene = ctrl.sp.getSceneNumber(
ctrl.sp.page2lines(pageNr)[0] - 1)

pagesDone = 0

while 1:
if (pagesDone >= pageCnt) or (pageNr >= len(ctrl.sp.pages)):
break
sy = self.PAGE_GAP
while (pageNr < len(ctrl.sp.pages)):
pagesDonePerRow = 0
sx = self.PAGE_GAP
while 1:
if (pagesDonePerRow >= pagesPerRow) or (pageNr >= len(ctrl.sp.pages)):
break

# we'd have to go back an arbitrary number of pages to get an
# accurate number for this in the worst case, so disable it
# altogether.
pager.sceneContNr = 0
# we'd have to go back an arbitrary number of pages to get an
# accurate number for this in the worst case, so disable it
# altogether.
pager.sceneContNr = 0

if pageCache:
pg = pageCache.getPage(pager, pageNr)
else:
pg = ctrl.sp.generatePMLPage(pager, pageNr, False,
doExtra)
if not pg:
break
if pageCache:
pg = pageCache.getPage(pager, pageNr)
else:
pg = ctrl.sp.generatePMLPage(pager, pageNr, False,
doExtra)
if not pg:
break

sx = pageGap + pagesDone * (ctrl.pageW + pageGap)
sy = pageGap
sx += pagesDonePerRow * (ctrl.pageW + self.PAGE_GAP)

dp = DisplayPage(pageNr, sx, sy, sx + ctrl.pageW,
sy + ctrl.pageH)
dpages.append(dp)
dp = DisplayPage(pageNr, sx, sy, sx + ctrl.pageW,
sy + ctrl.pageH)
dpages.append(dp)

for op in pg.ops:
if not isinstance(op, textOp):
continue
for op in pg.ops:
if not isinstance(op, textOp):
continue

texts.append(TextString(op.line, op.text,
int(sx + op.x * mm2p), int(sy + op.y * mm2p),
cfgGui.fonts[op.flags & 3], op.flags & pml.UNDERLINED))
texts.append(TextString(op.line, op.text,
int(sx + op.x * mm2p), int(sy + op.y * mm2p),
cfgGui.fonts[op.flags & 3], op.flags & pml.UNDERLINED))

pageNr += 1
pagesDone += 1
pageNr += 1
pagesDonePerRow += 1
sy += ctrl.pageH + self.PAGE_GAP

return (texts, dpages)

def getLineHeight(self, ctrl):
# the + 1.0 avoids occasional non-consecutive backgrounds for
# lines.
return int(ctrl.chY * ctrl.mm2p + 1.0)
def getDocumentHeight(self, ctrl) -> int:
pagesPerRow = max(1, (ctrl.GetClientSize().GetWidth() - self.PAGE_GAP) // (ctrl.pageW + self.PAGE_GAP))
rows = math.ceil((len(ctrl.sp.pages) - 1) / pagesPerRow)

return int(rows * (ctrl.pageH + self.PAGE_GAP) + 2 * self.PAGE_GAP)

def getPageWidth(self, ctrl):
return (ctrl.sp.cfg.paperWidth / ctrl.chX) *\
Expand Down

0 comments on commit bc5c718

Please sign in to comment.