From 6f0d3c089820a4a2cc3484e8411578e10dc891d9 Mon Sep 17 00:00:00 2001 From: ketmar Date: Tue, 22 Nov 2016 04:30:47 +0000 Subject: [PATCH] preparing for "consolization" FossilOrigin-Name: 33f0038896fca27d1a556f0fa88e953b02d03412fddc236ebcecbb5b13469320 --- xreader.d | 930 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 479 insertions(+), 451 deletions(-) diff --git a/xreader.d b/xreader.d index 4fc066c..83390ed 100644 --- a/xreader.d +++ b/xreader.d @@ -56,224 +56,530 @@ __gshared int oglConScale = 1; // ////////////////////////////////////////////////////////////////////////// // -void run (string bookFileName) { - int formatWorks = -1; - NVGContext vg = null; - PerfGraph fps; - __gshared bool fpsVisible = false; - BookText booktext; - string newBookFileName; +__gshared string bookFileName; - if (GWidth < MinWinWidth) GWidth = MinWinWidth; - if (GHeight < MinWinHeight) GHeight = MinWinHeight; +__gshared int formatWorks = -1; +__gshared NVGContext vg = null; +__gshared PerfGraph fps; +__gshared bool fpsVisible = false; +__gshared BookText bookText; +__gshared string newBookFileName; +__gshared uint[] posstack; +__gshared SimpleWindow sdwindow; +__gshared LayText laytext; +__gshared BookInfo[] recentFiles; +__gshared BookMetadata bookmeta; - uint[] posstack; +__gshared int textHeight; - booktext = loadBook(bookFileName); +__gshared int toMove = 0; // for smooth scroller +__gshared int topY = 0; +__gshared int arrowDir = 0; - //setOpenGLContextVersion(3, 2); // up to GLSL 150 - setOpenGLContextVersion(2, 0); // it's enough - //openGLContextCompatible = false; +__gshared int newYLine = -1; // index +__gshared float newYAlpha; +__gshared bool newYFade = false; +__gshared MonoTime nextFadeTime; - auto sdwindow = new SimpleWindow(GWidth, GHeight, booktext.title~" \xe2\x80\x94 "~booktext.authorFirst~" "~booktext.authorLast, OpenGlOptions.yes, Resizablity.allowResizing); - sdwindow.hideCursor(); // we will do our own - sdwindow.setMinSize(MinWinWidth, MinWinHeight); +__gshared int curImg = -1, curImgWhite = -1; +__gshared int mouseX = -666, mouseY = -666; +__gshared bool mouseHigh = false; +__gshared bool mouseHidden = false; +__gshared MonoTime lastMMove; +__gshared float mouseAlpha = 1.0f; +__gshared int mouseFadingAway = false; - auto stt = MonoTime.currTime; - auto prevt = MonoTime.currTime; - auto curt = prevt; - LayText laytext; - int textHeight = GHeight-8; - bool doSaveCheck = false; - MonoTime nextSaveTime; +__gshared bool needRedrawFlag = true; - MonoTime nextIfTime = MonoTime.currTime; +__gshared bool firstFormat = true; + +__gshared bool inGalaxyMap = false; +__gshared PopupMenu currPopup; +__gshared void delegate (int item) onPopupSelect; +__gshared int shipModelIndex = 0; +__gshared bool popupNoShipKill = false; - BookInfo[] recentFiles; - BookMetadata bookmeta; +__gshared bool doSaveCheck = false; +__gshared MonoTime nextSaveTime; - int toMove = 0; // for smooth scroller - int topY = 0; - int arrowDir = 0; - int newYLine = -1; // index - float newYAlpha; - bool newYFade = false; - MonoTime nextFadeTime; +// ////////////////////////////////////////////////////////////////////////// // +void refresh () { needRedrawFlag = true; } +void refreshed () { needRedrawFlag = false; } - int curImg = -1, curImgWhite = -1; - int mouseX = -666, mouseY = -666; - bool mouseHigh = false; - bool mouseHidden = false; - auto lastMMove = MonoTime.currTime; - float mouseAlpha = 1.0f; - int mouseFadingAway = false; +bool needRedraw () { + return (needRedrawFlag || (currPopup !is null && currPopup.needRedraw)); +} - bool needRedrawFlag = true; - bool firstFormat = true; +@property bool inMenu () { return (currPopup !is null); } +void closeMenu () { if (currPopup !is null) currPopup.destroy; currPopup = null; onPopupSelect = null; } - __gshared bool inGalaxyMap = false; - PopupMenu currPopup; - void delegate (int item) onPopupSelect; - int shipModelIndex = 0; - bool popupNoShipKill = false; - void refresh () { needRedrawFlag = true; } - void refreshed () { needRedrawFlag = false; } +void setShip (int idx) { + if (eliteShipFiles.length) { + import core.memory : GC; + if (idx >= eliteShipFiles.length) idx = cast(int)eliteShipFiles.length-1; + if (idx < 0) idx = 0; + if (shipModelIndex == idx && shipModel !is null) return; + // remove old ship + shipModelIndex = idx; + if (shipModel !is null) { + shipModel.glUnload(); + shipModel.freeData(); + shipModel.destroy; + shipModel = null; + } + GC.collect(); + // load new ship + try { + shipModel = new EliteModel(eliteShipFiles[shipModelIndex]); + shipModel.glUpload(); + shipModel.freeImages(); + } catch (Exception e) {} + //shipModel = eliteShips[shipModelIndex]; + GC.collect(); + } +} - bool needRedraw () { - return (needRedrawFlag || (currPopup !is null && currPopup.needRedraw)); +void ensureShipModel () { + if (eliteShipFiles.length && shipModel is null) { + import std.random : uniform; + setShip(uniform!"[)"(0, eliteShipFiles.length)); } +} - @property bool inMenu () { return (currPopup !is null); } - void closeMenu () { if (currPopup !is null) currPopup.destroy; currPopup = null; onPopupSelect = null; } +void freeShipModel () { + if (!showShip && !inMenu && shipModel !is null) { + import core.memory : GC; + shipModel.glUnload(); + shipModel.freeData(); + shipModel.destroy; + shipModel = null; + GC.collect(); + } +} - auto childTid = spawn(&reformatThreadFn, thisTid); - childTid.setMaxMailboxSize(128, OnCrowding.block); - thisTid.setMaxMailboxSize(128, OnCrowding.block); - void setShip (int idx) { - if (eliteShipFiles.length) { - import core.memory : GC; - if (idx >= eliteShipFiles.length) idx = cast(int)eliteShipFiles.length-1; - if (idx < 0) idx = 0; - if (shipModelIndex == idx && shipModel !is null) return; - // remove old ship - shipModelIndex = idx; - if (shipModel !is null) { - shipModel.glUnload(); - shipModel.freeData(); - shipModel.destroy; - shipModel = null; - } - GC.collect(); - // load new ship - try { - shipModel = new EliteModel(eliteShipFiles[shipModelIndex]); - shipModel.glUpload(); - shipModel.freeImages(); - } catch (Exception e) {} - //shipModel = eliteShips[shipModelIndex]; - GC.collect(); +void loadState () { + try { + int widx = -1; + xiniParse(VFile(stateFileName), + "wordindex", &widx, + ); + if (widx >= 0) goTo(widx); + } catch (Exception) {} +} + +void doSaveState (bool forced=false) { + if (!forced) { + if (formatWorks != 0) return; + if (!doSaveCheck) return; + auto ct = MonoTime.currTime; + if (ct < nextSaveTime) return; + } else { + if (laytext is null || laytext.lineCount == 0 || formatWorks != 0) return; + } + try { + auto fo = VFile(stateFileName, "w"); + if (laytext !is null && laytext.lineCount) { + auto lnum = laytext.findLineAtY(topY); + if (lnum >= 0) fo.writeln("wordindex=", laytext.line(lnum).wstart); } + } catch (Exception) {} + doSaveCheck = false; +} + +void stateChanged () { + if (!doSaveCheck) { + doSaveCheck = true; + nextSaveTime = MonoTime.currTime+10.seconds; } +} - void ensureShipModel () { - if (eliteShipFiles.length && shipModel is null) { - import std.random : uniform; - setShip(uniform!"[)"(0, eliteShipFiles.length)); - } + +void hardScrollBy (int delta) { + if (delta == 0 || laytext is null || laytext.lineCount == 0) return; + int oldY = topY; + topY += delta; + if (topY >= laytext.textHeight-textHeight) topY = cast(int)laytext.textHeight-textHeight; + if (topY < 0) topY = 0; + if (topY != oldY) { + stateChanged(); + refresh(); } +} - void freeShipModel () { - if (!showShip && !inMenu && shipModel !is null) { - import core.memory : GC; - shipModel.glUnload(); - shipModel.freeData(); - shipModel.destroy; - shipModel = null; - GC.collect(); - } +void scrollBy (int delta) { + if (delta == 0 || laytext is null || laytext.lineCount == 0) return; + toMove += delta; + newYFade = true; + newYAlpha = 1; + if (delta < 0) { + // scrolling up, mark top line + newYLine = laytext.findLineAtY(topY); + } else { + // scrolling down, mark bottom line + newYLine = laytext.findLineAtY(topY+textHeight-2); } + version(none) { + conwriteln("scrollBy: delta=", delta, "; newYLine=", newYLine, "; topLine=", laytext.findLineAtY(topY)); + } + if (newYLine < 0) newYFade = false; +} - void doSaveState (bool forced=false) { - if (!forced) { - if (formatWorks != 0) return; - if (!doSaveCheck) return; - auto ct = MonoTime.currTime; - if (ct < nextSaveTime) return; - } else { - if (laytext is null || laytext.lineCount == 0 || formatWorks != 0) return; - } - try { - auto fo = VFile(stateFileName, "w"); - if (laytext !is null && laytext.lineCount) { - auto lnum = laytext.findLineAtY(topY); - if (lnum >= 0) fo.writeln("wordindex=", laytext.line(lnum).wstart); - } - } catch (Exception) {} - doSaveCheck = false; + +void goHome () { + if (laytext is null) return; + if (topY != 0) { + topY = 0; + stateChanged(); + refresh(); } +} - void stateChanged () { - if (!doSaveCheck) { - doSaveCheck = true; - nextSaveTime = MonoTime.currTime+10.seconds; + +void goTo (uint widx) { + if (laytext is null) return; + auto lidx = laytext.findLineWithWord(widx); + if (lidx != -1) { + assert(lidx < laytext.lineCount); + toMove = 0; + if (topY != laytext.line(lidx).y) { + topY = laytext.line(lidx).y; + stateChanged(); + refresh(); + } + version(none) { + conwriteln("goto: widx=", widx, "; lidx=", lidx, "; fwn=", laytext.line(lidx).wstart, "; topY=", topY); + auto lnum = laytext.findLineAtY(topY); + conwriteln(" newlnum=", lnum, "; lidx.y=", laytext.line(lidx).y, "; lnum.y=", laytext.line(lnum).y); } } +} + + +void pushPosition () { + if (laytext is null || laytext.lineCount == 0) return; + auto lidx = laytext.findLineAtY(topY); + if (lidx >= 0) posstack ~= laytext.line(lidx).wstart; +} - void hardScrollBy (int delta) { - if (delta == 0 || laytext is null || laytext.lineCount == 0) return; - int oldY = topY; - topY += delta; - if (topY >= laytext.textHeight-textHeight) topY = cast(int)laytext.textHeight-textHeight; - if (topY < 0) topY = 0; - if (topY != oldY) { +void popPosition () { + if (posstack.length == 0) return; + auto widx = posstack[$-1]; + posstack.length -= 1; + posstack.assumeSafeAppend; + goTo(widx); +} + + +void gotoSection (int sn) { + if (laytext is null || laytext.lineCount == 0 || bookmeta is null) return; + if (sn < 0 || sn >= bookmeta.sections.length) return; + auto lidx = laytext.findLineWithWord(bookmeta.sections[sn].wordidx); + if (lidx >= 0) { + auto newY = laytext.line(lidx).y; + if (newY != topY) { + topY = newY; stateChanged(); refresh(); } } +} - void scrollBy (int delta) { - if (delta == 0 || laytext is null || laytext.lineCount == 0) return; - toMove += delta; - newYFade = true; - newYAlpha = 1; - if (delta < 0) { - // scrolling up, mark top line - newYLine = laytext.findLineAtY(topY); - } else { - // scrolling down, mark bottom line - newYLine = laytext.findLineAtY(topY+textHeight-2); + +void relayout (bool forced=false) { + if (laytext !is null) { + uint widx; + auto lidx = laytext.findLineAtY(topY); + if (lidx >= 0) widx = laytext.line(lidx).wstart; + int maxWidth = GWidth-4-2-BND_SCROLLBAR_WIDTH-2; + //if (maxWidth < MinWinWidth) maxWidth = MinWinWidth; + { + import core.time; + auto stt = MonoTime.currTime; + laytext.relayout(maxWidth, forced); + auto ett = MonoTime.currTime-stt; + conwriteln("relayouted in ", ett.total!"msecs", " milliseconds; lines:", laytext.lineCount, "; words:", laytext.nextWordIndex); } - version(none) { - conwriteln("scrollBy: delta=", delta, "; newYLine=", newYLine, "; topLine=", laytext.findLineAtY(topY)); + goTo(widx); + refresh(); + } +} + + +void drawShipName () { + if (shipModel is null || shipModel.name.length == 0) return; + vg.fontFaceId(uiFont); + vg.textAlign(NVGTextAlign.H.Left, NVGTextAlign.V.Baseline); + vg.fontSize(fsizeUI); + auto w = vg.bndLabelWidth(-1, shipModel.name)+8; + float h = BND_WIDGET_HEIGHT+8; + float mx = (GWidth-w)/2.0; + float my = (GHeight-h)-8; + vg.bndMenuBackground(mx, my, w, h, BND_CORNER_NONE); + vg.bndMenuItem(mx+4, my+4, w-8, BND_WIDGET_HEIGHT, BND_DEFAULT, -1, shipModel.name); + if (shipModel.dispName && shipModel.dispName != shipModel.name) { + my -= BND_WIDGET_HEIGHT+16; + w = vg.bndLabelWidth(-1, shipModel.dispName)+8; + mx = (GWidth-w)/2.0; + vg.bndMenuBackground(mx, my, w, h, BND_CORNER_NONE); + vg.bndMenuItem(mx+4, my+4, w-8, BND_WIDGET_HEIGHT, BND_DEFAULT, -1, shipModel.dispName); + } +} + + +void createSectionMenu () { + closeMenu(); + //conwriteln("lc=", laytext.lineCount, "; bm: ", (bookmeta !is null)); + if (laytext is null || laytext.lineCount == 0 || bookmeta is null) { freeShipModel(); return; } + currPopup = new PopupMenu(vg, "Sections"d, () { + dstring[] items; + foreach (const ref sc; bookmeta.sections) items ~= sc.name; + return items; + }); + //conwriteln(currPopup.items.length); + // find current section + currPopup.curItemIdx = 0; + auto lidx = laytext.findLineAtY(topY); + if (lidx >= 0 && bookmeta.sections.length > 0) { + foreach (immutable sidx, const ref sc; bookmeta.sections) { + auto sline = laytext.findLineWithWord(sc.wordidx); + if (sline >= 0 && lidx >= sline) currPopup.curItemIdx = cast(int)sidx; } - if (newYLine < 0) newYFade = false; } + onPopupSelect = (int item) { gotoSection(item); }; +} - void goHome () { - if (laytext is null) return; - if (topY != 0) { - topY = 0; - stateChanged(); - refresh(); + +void createQuitMenu (bool wantYes) { + closeMenu(); + currPopup = new PopupMenu(vg, "Quit?"d, () { + return ["Yes"d, "No"d]; + }); + currPopup.curItemIdx = (wantYes ? 0 : 1); + onPopupSelect = (int item) { if (item == 0) concmd("quit"); }; +} + + +void createRecentMenu () { + closeMenu(); + if (recentFiles.length == 0) recentFiles = loadDetailedHistory(); + if (recentFiles.length == 0) { freeShipModel(); return; } + currPopup = new PopupMenu(vg, "Recent files"d, () { + import std.conv : to; + dstring[] res; + foreach (const ref BookInfo bi; recentFiles) { + string s = bi.title; + if (bi.seqname.length) { + s ~= " ("; + if (bi.seqnum) { s ~= to!string(bi.seqnum); s ~= ": "; } + //conwriteln(bi.seqname); + s ~= bi.seqname; + s ~= ")"; + } + if (bi.author.length) { s ~= " \xe2\x80\x94 "; s ~= bi.author; } + res ~= s.to!dstring; } + return res; + }); + currPopup.curItemIdx = cast(int)recentFiles.length-1; + onPopupSelect = (int item) { + newBookFileName = recentFiles[item].diskfile; + popupNoShipKill = true; + }; +} + + +bool menuKey (KeyEvent event) { + if (formatWorks != 0) return false; + if (!inMenu) return false; + if (inGalaxyMap) return false; + if (!event.pressed) return false; + auto res = currPopup.onKey(event); + if (res == PopupMenu.Close) { + closeMenu(); + freeShipModel(); + refresh(); + } else if (res >= 0) { + if (onPopupSelect !is null) onPopupSelect(res); + closeMenu(); + if (popupNoShipKill) popupNoShipKill = false; else freeShipModel(); + refresh(); } + return true; +} + + +bool menuMouse (MouseEvent event) { + if (formatWorks != 0) return false; + if (!inMenu) return false; + if (inGalaxyMap) return false; + auto res = currPopup.onMouse(event); + if (res == PopupMenu.Close) { + closeMenu(); + freeShipModel(); + refresh(); + } else if (res >= 0) { + if (onPopupSelect !is null) onPopupSelect(res); + closeMenu(); + if (popupNoShipKill) popupNoShipKill = false; else freeShipModel(); + refresh(); + } + return true; +} + + +bool readerKey (KeyEvent event) { + if (formatWorks != 0) return false; + if (!event.pressed) { + switch (event.key) { + case Key.Up: arrowDir = 0; return true; + case Key.Down: arrowDir = 0; return true; + default: + } + return false; + } + switch (event.key) { + case Key.Space: + if (event.modifierState&ModifierState.shift) { + //goto case Key.PageUp; + hardScrollBy(toMove); toMove = 0; + scrollBy(-textHeight/3*2); + } else { + //goto case Key.PageDown; + hardScrollBy(toMove); toMove = 0; + scrollBy(textHeight/3*2); + } + break; + case Key.Backspace: + popPosition(); + break; + case Key.PageUp: + hardScrollBy(toMove); toMove = 0; + hardScrollBy(-(textHeight > 32 ? textHeight-32 : textHeight)); + break; + case Key.PageDown: + hardScrollBy(toMove); toMove = 0; + hardScrollBy(textHeight > 32 ? textHeight-32 : textHeight); + break; + case Key.Up: + //scrollBy(-8); + arrowDir = -1; + break; + case Key.Down: + //scrollBy(8); + arrowDir = 1; + break; + case Key.H: + goHome(); + break; + default: + } + return true; +} - void goTo (uint widx) { - if (laytext is null) return; - auto lidx = laytext.findLineWithWord(widx); - if (lidx != -1) { - assert(lidx < laytext.lineCount); - toMove = 0; - if (topY != laytext.line(lidx).y) { - topY = laytext.line(lidx).y; - stateChanged(); + +bool controlKey (KeyEvent event) { + if (!event.pressed) return false; + switch (event.key) { + case Key.Escape: + if (inGalaxyMap) { inGalaxyMap = false; refresh(); return true; } + if (inMenu) { closeMenu(); freeShipModel(); refresh(); return true; } + if (showShip) { showShip = false; freeShipModel(); refresh(); return true; } + ensureShipModel(); + createQuitMenu(true); + refresh(); + return true; + case Key.P: if (event.modifierState == ModifierState.ctrl) { concmd("r_fps toggle"); return true; } break; + case Key.I: if (event.modifierState == ModifierState.ctrl) { concmd("r_interference toggle"); return true; } break; + case Key.N: if (event.modifierState == ModifierState.ctrl) { concmd("r_sbleft toggle"); return true; } break; + case Key.C: if (event.modifierState == ModifierState.ctrl) { if (addIf()) refresh(); return true; } break; + case Key.E: + if (event.modifierState == ModifierState.ctrl && eliteShipFiles.length > 0) { + if (!inMenu) { + showShip = !showShip; + if (showShip) ensureShipModel(); else freeShipModel(); + refresh(); + } + return true; + } + break; + case Key.Q: if (event.modifierState == ModifierState.ctrl) { concmd("quit"); return true; } break; + case Key.B: if (formatWorks == 0 && !inMenu && !inGalaxyMap && event.modifierState == ModifierState.ctrl) { pushPosition(); return true; } break; + case Key.S: + if (formatWorks == 0 && !showShip && !inMenu && !inGalaxyMap) { + ensureShipModel(); + createSectionMenu(); refresh(); } - version(none) { - conwriteln("goto: widx=", widx, "; lidx=", lidx, "; fwn=", laytext.line(lidx).wstart, "; topY=", topY); - auto lnum = laytext.findLineAtY(topY); - conwriteln(" newlnum=", lnum, "; lidx.y=", laytext.line(lidx).y, "; lnum.y=", laytext.line(lnum).y); + break; + case Key.L: + if (formatWorks == 0 && event.modifierState == ModifierState.alt) { + ensureShipModel(); + createRecentMenu(); + refresh(); } - } + break; + case Key.M: + if (!inMenu && !showShip) { + inGalaxyMap = !inGalaxyMap; + refresh(); + } + break; + case Key.R: + if (formatWorks == 0 && event.modifierState == ModifierState.ctrl) relayout(true); + break; + case Key.Home: if (showShip) { setShip(0); return true; } break; + case Key.End: if (showShip) { setShip(cast(int)eliteShipFiles.length); return true; } break; + case Key.Up: case Key.Left: if (showShip) { setShip(shipModelIndex-1); return true; } break; + case Key.Down: case Key.Right: if (showShip) { setShip(shipModelIndex+1); return true; } break; + default: } + return showShip; +} - void loadState () { - try { - int widx = -1; - xiniParse(VFile(stateFileName), - "wordindex", &widx, - ); - if (widx >= 0) goTo(widx); - } catch (Exception) {} - } +int startX () { pragma(inline, true); return (sbLeft ? 2+BND_SCROLLBAR_WIDTH+2 : 4); } +int endX () { pragma(inline, true); return startX+GWidth-4-2-BND_SCROLLBAR_WIDTH-2-1; } + +int startY () { pragma(inline, true); return (GHeight-textHeight)/2; } +int endY () { pragma(inline, true); return startY+textHeight-1; } + + +// ////////////////////////////////////////////////////////////////////////// // +void run () { + if (GWidth < MinWinWidth) GWidth = MinWinWidth; + if (GHeight < MinWinHeight) GHeight = MinWinHeight; + + bookText = loadBook(bookFileName); + + //setOpenGLContextVersion(3, 2); // up to GLSL 150 + setOpenGLContextVersion(2, 0); // it's enough + //openGLContextCompatible = false; + + sdwindow = new SimpleWindow(GWidth, GHeight, bookText.title~" \xe2\x80\x94 "~bookText.authorFirst~" "~bookText.authorLast, OpenGlOptions.yes, Resizablity.allowResizing); + sdwindow.hideCursor(); // we will do our own + sdwindow.setMinSize(MinWinWidth, MinWinHeight); + + version(X11) sdwindow.closeQuery = delegate () { concmd("quit"); }; + + auto stt = MonoTime.currTime; + auto prevt = MonoTime.currTime; + auto curt = prevt; + textHeight = GHeight-8; + + MonoTime nextIfTime = MonoTime.currTime; + + lastMMove = MonoTime.currTime; + + auto childTid = spawn(&reformatThreadFn, thisTid); + childTid.setMaxMailboxSize(128, OnCrowding.block); + thisTid.setMaxMailboxSize(128, OnCrowding.block); void loadAndFormat (string filename) { assert(formatWorks <= 0); - booktext = null; + bookText = null; laytext = null; newYLine = -1; //formatWorks = -1; //FIXME @@ -283,7 +589,7 @@ void run (string bookFileName) { recentFiles = null; arrowDir = 0; //sdwindow.redrawOpenGlSceneNow(); - //booktext = loadBook(newBookFileName); + //bookText = loadBook(newBookFileName); //newBookFileName = null; //reformat(); //if (formatWorks < 0) formatWorks = 1; else ++formatWorks; @@ -295,7 +601,7 @@ void run (string bookFileName) { void reformat () { if (formatWorks < 0) formatWorks = 1; else ++formatWorks; - childTid.send(ReformatWork(cast(shared)booktext, null, GWidth, GHeight)); + childTid.send(ReformatWork(cast(shared)bookText, null, GWidth, GHeight)); refresh(); } @@ -311,11 +617,11 @@ void run (string bookFileName) { BookText bt = cast(BookText)w.booktext; w.booktext = null; - if (bt !is booktext) { - booktext = bt; + if (bt !is bookText) { + bookText = bt; bookmeta = meta; firstFormat = true; - sdwindow.title = booktext.title~" \xe2\x80\x94 "~booktext.authorFirst~" "~booktext.authorLast; + sdwindow.title = bookText.title~" \xe2\x80\x94 "~bookText.authorFirst~" "~bookText.authorLast; } else if (bookmeta is null) { bookmeta = meta; } @@ -350,36 +656,6 @@ void run (string bookFileName) { refresh(); } - void pushPosition () { - if (laytext is null || laytext.lineCount == 0) return; - auto lidx = laytext.findLineAtY(topY); - if (lidx >= 0) posstack ~= laytext.line(lidx).wstart; - } - - void popPosition () { - if (posstack.length == 0) return; - auto widx = posstack[$-1]; - posstack.length -= 1; - posstack.assumeSafeAppend; - goTo(widx); - } - - void gotoSection (int sn) { - if (laytext is null || laytext.lineCount == 0 || bookmeta is null) return; - if (sn < 0 || sn >= bookmeta.sections.length) return; - auto lidx = laytext.findLineWithWord(bookmeta.sections[sn].wordidx); - if (lidx >= 0) { - auto newY = laytext.line(lidx).y; - if (newY != topY) { - topY = newY; - stateChanged(); - refresh(); - } - } - } - - version(X11) sdwindow.closeQuery = delegate () { concmd("quit"); }; - void closeWindow () { doSaveState(true); // forced state save if (!sdwindow.closed && vg !is null) { @@ -426,25 +702,6 @@ void run (string bookFileName) { refresh(); }; - void relayout (bool forced=false) { - if (laytext !is null) { - uint widx; - auto lidx = laytext.findLineAtY(topY); - if (lidx >= 0) widx = laytext.line(lidx).wstart; - int maxWidth = GWidth-4-2-BND_SCROLLBAR_WIDTH-2; - //if (maxWidth < MinWinWidth) maxWidth = MinWinWidth; - { - import core.time; - auto stt = MonoTime.currTime; - laytext.relayout(maxWidth, forced); - auto ett = MonoTime.currTime-stt; - conwriteln("relayouted in ", ett.total!"msecs", " milliseconds; lines:", laytext.lineCount, "; words:", laytext.nextWordIndex); - } - goTo(widx); - refresh(); - } - } - sdwindow.windowResized = delegate (int w, int h) { //conwriteln("w=", w, "; h=", h); //if (w < MinWinWidth) w = MinWinWidth; @@ -458,236 +715,6 @@ void run (string bookFileName) { refresh(); }; - void drawShipName () { - if (shipModel is null || shipModel.name.length == 0) return; - vg.fontFaceId(uiFont); - vg.textAlign(NVGTextAlign.H.Left, NVGTextAlign.V.Baseline); - vg.fontSize(fsizeUI); - auto w = vg.bndLabelWidth(-1, shipModel.name)+8; - float h = BND_WIDGET_HEIGHT+8; - float mx = (GWidth-w)/2.0; - float my = (GHeight-h)-8; - vg.bndMenuBackground(mx, my, w, h, BND_CORNER_NONE); - vg.bndMenuItem(mx+4, my+4, w-8, BND_WIDGET_HEIGHT, BND_DEFAULT, -1, shipModel.name); - if (shipModel.dispName && shipModel.dispName != shipModel.name) { - my -= BND_WIDGET_HEIGHT+16; - w = vg.bndLabelWidth(-1, shipModel.dispName)+8; - mx = (GWidth-w)/2.0; - vg.bndMenuBackground(mx, my, w, h, BND_CORNER_NONE); - vg.bndMenuItem(mx+4, my+4, w-8, BND_WIDGET_HEIGHT, BND_DEFAULT, -1, shipModel.dispName); - } - } - - void createSectionMenu () { - closeMenu(); - //conwriteln("lc=", laytext.lineCount, "; bm: ", (bookmeta !is null)); - if (laytext is null || laytext.lineCount == 0 || bookmeta is null) { freeShipModel(); return; } - currPopup = new PopupMenu(vg, "Sections"d, () { - dstring[] items; - foreach (const ref sc; bookmeta.sections) items ~= sc.name; - return items; - }); - //conwriteln(currPopup.items.length); - // find current section - currPopup.curItemIdx = 0; - auto lidx = laytext.findLineAtY(topY); - if (lidx >= 0 && bookmeta.sections.length > 0) { - foreach (immutable sidx, const ref sc; bookmeta.sections) { - auto sline = laytext.findLineWithWord(sc.wordidx); - if (sline >= 0 && lidx >= sline) currPopup.curItemIdx = cast(int)sidx; - } - } - onPopupSelect = (int item) { gotoSection(item); }; - } - - void createQuitMenu (bool wantYes) { - closeMenu(); - currPopup = new PopupMenu(vg, "Quit?"d, () { - return ["Yes"d, "No"d]; - }); - currPopup.curItemIdx = (wantYes ? 0 : 1); - onPopupSelect = (int item) { if (item == 0) concmd("quit"); }; - } - - void createRecentMenu () { - closeMenu(); - if (recentFiles.length == 0) recentFiles = loadDetailedHistory(); - if (recentFiles.length == 0) { freeShipModel(); return; } - currPopup = new PopupMenu(vg, "Recent files"d, () { - import std.conv : to; - dstring[] res; - foreach (const ref BookInfo bi; recentFiles) { - string s = bi.title; - if (bi.seqname.length) { - s ~= " ("; - if (bi.seqnum) { s ~= to!string(bi.seqnum); s ~= ": "; } - //conwriteln(bi.seqname); - s ~= bi.seqname; - s ~= ")"; - } - if (bi.author.length) { s ~= " \xe2\x80\x94 "; s ~= bi.author; } - res ~= s.to!dstring; - } - return res; - }); - currPopup.curItemIdx = cast(int)recentFiles.length-1; - onPopupSelect = (int item) { - newBookFileName = recentFiles[item].diskfile; - popupNoShipKill = true; - }; - } - - bool menuKey (KeyEvent event) { - if (formatWorks != 0) return false; - if (!inMenu) return false; - if (inGalaxyMap) return false; - if (!event.pressed) return false; - auto res = currPopup.onKey(event); - if (res == PopupMenu.Close) { - closeMenu(); - freeShipModel(); - refresh(); - } else if (res >= 0) { - if (onPopupSelect !is null) onPopupSelect(res); - closeMenu(); - if (popupNoShipKill) popupNoShipKill = false; else freeShipModel(); - refresh(); - } - return true; - } - - bool menuMouse (MouseEvent event) { - if (formatWorks != 0) return false; - if (!inMenu) return false; - if (inGalaxyMap) return false; - auto res = currPopup.onMouse(event); - if (res == PopupMenu.Close) { - closeMenu(); - freeShipModel(); - refresh(); - } else if (res >= 0) { - if (onPopupSelect !is null) onPopupSelect(res); - closeMenu(); - if (popupNoShipKill) popupNoShipKill = false; else freeShipModel(); - refresh(); - } - return true; - } - - bool readerKey (KeyEvent event) { - if (formatWorks != 0) return false; - if (!event.pressed) { - switch (event.key) { - case Key.Up: arrowDir = 0; return true; - case Key.Down: arrowDir = 0; return true; - default: - } - return false; - } - switch (event.key) { - case Key.Space: - if (event.modifierState&ModifierState.shift) { - //goto case Key.PageUp; - hardScrollBy(toMove); toMove = 0; - scrollBy(-textHeight/3*2); - } else { - //goto case Key.PageDown; - hardScrollBy(toMove); toMove = 0; - scrollBy(textHeight/3*2); - } - break; - case Key.Backspace: - popPosition(); - break; - case Key.PageUp: - hardScrollBy(toMove); toMove = 0; - hardScrollBy(-(textHeight > 32 ? textHeight-32 : textHeight)); - break; - case Key.PageDown: - hardScrollBy(toMove); toMove = 0; - hardScrollBy(textHeight > 32 ? textHeight-32 : textHeight); - break; - case Key.Up: - //scrollBy(-8); - arrowDir = -1; - break; - case Key.Down: - //scrollBy(8); - arrowDir = 1; - break; - case Key.H: - goHome(); - break; - default: - } - return true; - } - - bool controlKey (KeyEvent event) { - if (!event.pressed) return false; - switch (event.key) { - case Key.Escape: - if (inGalaxyMap) { inGalaxyMap = false; refresh(); return true; } - if (inMenu) { closeMenu(); freeShipModel(); refresh(); return true; } - if (showShip) { showShip = false; freeShipModel(); refresh(); return true; } - ensureShipModel(); - createQuitMenu(true); - refresh(); - return true; - case Key.P: if (event.modifierState == ModifierState.ctrl) { concmd("r_fps toggle"); refresh(); return true; } break; - case Key.I: if (event.modifierState == ModifierState.ctrl) { concmd("r_interference toggle"); refresh(); return true; } break; - case Key.N: if (event.modifierState == ModifierState.ctrl) { concmd("r_sbleft toggle"); refresh(); return true; } break; - case Key.C: if (event.modifierState == ModifierState.ctrl) { if (addIf()) refresh(); return true; } break; - case Key.E: - if (event.modifierState == ModifierState.ctrl && eliteShipFiles.length > 0) { - if (!inMenu) { - showShip = !showShip; - if (showShip) ensureShipModel(); else freeShipModel(); - refresh(); - } - return true; - } - break; - case Key.Q: if (event.modifierState == ModifierState.ctrl) { concmd("quit"); return true; } break; - case Key.B: if (formatWorks == 0 && !inMenu && !inGalaxyMap && event.modifierState == ModifierState.ctrl) { pushPosition(); return true; } break; - case Key.S: - if (formatWorks == 0 && !showShip && !inMenu && !inGalaxyMap) { - ensureShipModel(); - createSectionMenu(); - refresh(); - } - break; - case Key.L: - if (formatWorks == 0 && event.modifierState == ModifierState.alt) { - ensureShipModel(); - createRecentMenu(); - refresh(); - } - break; - case Key.M: - if (!inMenu && !showShip) { - inGalaxyMap = !inGalaxyMap; - refresh(); - } - break; - case Key.R: - if (formatWorks == 0 && event.modifierState == ModifierState.ctrl) relayout(true); - break; - case Key.Home: if (showShip) { setShip(0); return true; } break; - case Key.End: if (showShip) { setShip(cast(int)eliteShipFiles.length); return true; } break; - case Key.Up: case Key.Left: if (showShip) { setShip(shipModelIndex-1); return true; } break; - case Key.Down: case Key.Right: if (showShip) { setShip(shipModelIndex+1); return true; } break; - default: - } - return showShip; - } - - static int startX () { pragma(inline, true); return (sbLeft ? 2+BND_SCROLLBAR_WIDTH+2 : 4); } - static int endX () { pragma(inline, true); return startX+GWidth-4-2-BND_SCROLLBAR_WIDTH-2-1; } - - int startY () { pragma(inline, true); return (GHeight-textHeight)/2; } - int endY () { pragma(inline, true); return startY+textHeight-1; } - sdwindow.redrawOpenGlScene = delegate () { if (isQuitRequested) return; @@ -1179,5 +1206,6 @@ void main (string[] args) { readConfig(); - run(args[1]); + bookFileName = args[1]; + run(); } -- 2.11.4.GIT