summaryrefslogtreecommitdiffstats
path: root/fbreader/src/blockTree/FBReaderNode.cpp
diff options
context:
space:
mode:
authorMichele Calgaro <[email protected]>2024-05-11 21:28:48 +0900
committerMichele Calgaro <[email protected]>2024-05-11 21:28:48 +0900
commit2462d03f322261bd616721c2b2065c4004b36c9c (patch)
tree239947a0737bb8386703a1497f12c09aebd3080a /fbreader/src/blockTree/FBReaderNode.cpp
downloadtde-ebook-reader-2462d03f322261bd616721c2b2065c4004b36c9c.tar.gz
tde-ebook-reader-2462d03f322261bd616721c2b2065c4004b36c9c.zip
Initial import (as is) from Debian Snapshot's 'fbreader' source code (https://snapshot.debian.org/package/fbreader/0.99.4%2Bdfsg-6).
The Debian code is provided under GPL2 license. Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'fbreader/src/blockTree/FBReaderNode.cpp')
-rw-r--r--fbreader/src/blockTree/FBReaderNode.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/fbreader/src/blockTree/FBReaderNode.cpp b/fbreader/src/blockTree/FBReaderNode.cpp
new file mode 100644
index 0000000..dc72d1e
--- /dev/null
+++ b/fbreader/src/blockTree/FBReaderNode.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2009-2012 Geometer Plus <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <ZLResource.h>
+#include <ZLibrary.h>
+#include <ZLFileImage.h>
+
+#include "FBReaderNode.h"
+
+#include "../fbreader/FBReader.h"
+#include "../options/FBOptions.h"
+#include "../options/FBTextStyle.h"
+
+const ZLTypeId FBReaderNode::TYPE_ID(ZLBlockTreeNode::TYPE_ID);
+
+class FBReaderNode::ExpandTreeAction : public ZLRunnableWithKey {
+
+public:
+ ExpandTreeAction(FBReaderNode &node);
+ void run();
+ ZLResourceKey key() const;
+
+private:
+ FBReaderNode &myNode;
+};
+
+std::map<std::string,shared_ptr<const ZLImage> > FBReaderNode::ourDefaultCovers;
+
+FBReaderNode::FBReaderNode(ZLBlockTreeNode *parent, std::size_t atPosition) : ZLBlockTreeNode(parent, atPosition), myCoverImageIsStored(false), myIsInitialized(false) {
+}
+
+void FBReaderNode::init() {
+}
+
+bool FBReaderNode::highlighted() const {
+ return false;
+}
+
+FBReaderNode::~FBReaderNode() {
+}
+
+const ZLTypeId &FBReaderNode::typeId() const {
+ return TYPE_ID;
+}
+
+shared_ptr<const ZLImage> FBReaderNode::coverImage() const {
+ if (!myCoverImageIsStored) {
+ myCoverImageIsStored = true;
+ myStoredCoverImage = extractCoverImage();
+ }
+ return myStoredCoverImage;
+}
+
+void FBReaderNode::drawCover(ZLPaintContext &context, int vOffset) {
+ drawCoverReal(context, vOffset);
+}
+
+void FBReaderNode::drawCoverReal(ZLPaintContext &context, int vOffset) {
+ shared_ptr<const ZLImage> cover = coverImage();
+ if (cover.isNull()) {
+ return;
+ }
+
+ shared_ptr<ZLImageData> coverData = ZLImageManager::Instance().imageData(*cover);
+ if (coverData.isNull()) {
+ return;
+ }
+
+ const FBTextStyle &style = FBTextStyle::Instance();
+ const int unit = unitSize(context, style);
+ const int h = unit * 9 / 2, w = h * 3 / 4;
+ vOffset += unit / 2;
+ const int hOffset = level() * unit * 3 - unit * 2;
+
+ const int origWidth = context.imageWidth(*coverData);
+ const int origHeight = context.imageHeight(*coverData);
+ if (origWidth == 0 || origHeight == 0) {
+ return;
+ }
+
+ int coeff = std::min(w / origWidth, h / origHeight);
+ if (coeff == 0) {
+ coeff = 1;
+ }
+ int width = coeff * origWidth;
+ int height = coeff * origHeight;
+ if (width > w || height > h) {
+ width = context.imageWidth(*coverData, w, h, ZLPaintContext::SCALE_REDUCE_SIZE);
+ height = context.imageHeight(*coverData, w, h, ZLPaintContext::SCALE_REDUCE_SIZE);
+ }
+ context.drawImage(hOffset + (w - width) / 2, vOffset + (h + height) / 2, *coverData, width, height, ZLPaintContext::SCALE_FIT_TO_SIZE);
+}
+
+void FBReaderNode::drawTitle(ZLPaintContext &context, int vOffset) {
+ const FBTextStyle &style = FBTextStyle::Instance();
+ const int unit = unitSize(context, style);
+ const int hOffset = level() * unit * 3 + unit * 2;
+
+ context.setColor(highlighted() ?
+ FBOptions::Instance().colorOption(ZLTextStyle::HIGHLIGHTED_TEXT).value() :
+ FBOptions::Instance().RegularTextColorOption.value());
+ context.setFont(style.fontFamily(), style.fontSize(), style.bold(), style.italic());
+
+ const std::string text = title();
+ context.drawString(hOffset, vOffset + 2 * unit, text.data(), text.size(), false);
+}
+
+void FBReaderNode::drawSummary(ZLPaintContext &context, int vOffset) {
+ const std::string text = summary();
+ if (text.empty()) {
+ return;
+ }
+
+ const FBTextStyle &style = FBTextStyle::Instance();
+ const int unit = unitSize(context, style);
+ const int hOffset = level() * unit * 3 + unit * 2;
+
+ context.setColor(highlighted() ?
+ FBOptions::Instance().colorOption(ZLTextStyle::HIGHLIGHTED_TEXT).value() :
+ FBOptions::Instance().RegularTextColorOption.value());
+ context.setFont(style.fontFamily(), style.fontSize() * 2 / 3, style.bold(), style.italic());
+
+ context.drawString(hOffset, vOffset + 13 * unit / 4, text.data(), text.size(), false);
+}
+
+void FBReaderNode::drawHyperlink(ZLPaintContext &context, int &hOffset, int &vOffset, shared_ptr<ZLRunnableWithKey> action, bool auxiliary) {
+ // auxiliary makes font size and hSkip to be 70% of their normal sizes
+ if (action.isNull() || !action->makesSense()) {
+ return;
+ }
+
+ const FBTextStyle &style = FBTextStyle::Instance();
+ const int unit = unitSize(context, style);
+ const int h = auxiliary ? (unit * 11 / 2) : (unit * 9 / 2);
+ const int left = hOffset + level() * unit * 3 + unit * 2;
+
+ context.setColor(FBOptions::Instance().colorOption("internal").value());
+ context.setFont(
+ style.fontFamily(),
+ auxiliary ? (7 * style.fontSize() / 15) : (style.fontSize() * 2 / 3),
+ style.bold(),
+ style.italic()
+ );
+
+ const std::string text = action->text(resource());
+ const int stringW = context.stringWidth(text.data(), text.size(), false);
+ const int stringH = context.stringHeight();
+ context.drawString(left, vOffset + h, text.data(), text.size(), false);
+ addHyperlink(left, h - stringH, left + stringW, h, action);
+ hOffset += stringW + 4 * context.spaceWidth();
+}
+
+FBReaderNode::ExpandTreeAction::ExpandTreeAction(FBReaderNode &node) : myNode(node) {
+}
+
+void FBReaderNode::ExpandTreeAction::run() {
+ myNode.expandOrCollapseSubtree();
+ FBReader::Instance().refreshWindow();
+}
+
+ZLResourceKey FBReaderNode::ExpandTreeAction::key() const {
+ return ZLResourceKey(myNode.isOpen() ? "collapseTree" : "expandTree");
+}
+
+void FBReaderNode::expandOrCollapseSubtree() {
+ if (isOpen()) {
+ open(false);
+ } else if (!children().empty()) {
+ open(true);
+ if (view().visibilityMode(this) != ZLBlockTreeView::INVISIBLE) {
+ ZLBlockTreeNode *lastChild = children().back();
+ while (view().visibilityMode(lastChild) != ZLBlockTreeView::VISIBLE &&
+ this != view().firstVisibleNode()) {
+ view().setFirstVisibleNode(view().firstVisibleNode()->next());
+ }
+ }
+ }
+}
+
+void FBReaderNode::registerAction(shared_ptr<ZLRunnableWithKey> action, bool auxiliary) {
+ if (!action.isNull()) {
+ myActions.push_back(std::make_pair(action, auxiliary));
+ }
+}
+
+void FBReaderNode::registerExpandTreeAction() {
+ registerAction(new ExpandTreeAction(*this));
+}
+
+shared_ptr<const ZLImage> FBReaderNode::defaultCoverImage(const std::string &id) {
+ shared_ptr<const ZLImage> cover = ourDefaultCovers[id];
+ if (cover.isNull()) {
+ cover = new ZLFileImage(
+ ZLFile(ZLibrary::ApplicationImageDirectory() + ZLibrary::FileNameDelimiter + id), 0
+ );
+ ourDefaultCovers[id] = cover;
+ }
+ return cover;
+}
+
+int FBReaderNode::height(ZLPaintContext &context) const {
+ bool hasAuxHyperlink = false;
+ for (std::vector<std::pair<shared_ptr<ZLRunnableWithKey>,bool> >::const_iterator it = myActions.begin(); it != myActions.end(); ++it) {
+ if (it->second && it->first->makesSense()) {
+ hasAuxHyperlink = true;
+ break;
+ }
+ }
+ return
+ unitSize(context, FBTextStyle::Instance()) *
+ (hasAuxHyperlink ? 13 : 11) / 2;
+}
+
+int FBReaderNode::unitSize(ZLPaintContext &context, const FBTextStyle &style) const {
+ context.setFont(style.fontFamily(), style.fontSize(), style.bold(), style.italic());
+ return (context.stringHeight() * 2 + 2) / 3;
+}
+
+std::string FBReaderNode::summary() const {
+ std::string result;
+ int count = 0;
+ const ZLBlockTreeNode::List &subNodes = children();
+ ZLBlockTreeNode::List::const_iterator it = subNodes.begin();
+ for (; it != subNodes.end() && count < 3; ++it, ++count) {
+ if (count > 0) {
+ result += ", ";
+ }
+ result += ((const FBReaderNode*)*it)->title();
+ }
+ if (it != subNodes.end()) {
+ result += ", ...";
+ }
+ return result;
+}
+
+void FBReaderNode::paint(ZLPaintContext &context, int vOffset) {
+ if (!myIsInitialized) {
+ init();
+ myIsInitialized = true;
+ }
+
+ removeAllHyperlinks();
+
+ drawCover(context, vOffset);
+ drawTitle(context, vOffset);
+ drawSummary(context, vOffset);
+
+ int left = 0;
+ int auxLeft = 0;
+ for (std::vector<std::pair<shared_ptr<ZLRunnableWithKey>,bool> >::const_iterator it = myActions.begin(); it != myActions.end(); ++it) {
+ if (it->first->makesSense()) {
+ if (it->second) {
+ drawHyperlink(context, auxLeft, vOffset, it->first, true);
+ } else {
+ drawHyperlink(context, left, vOffset, it->first);
+ }
+ }
+ }
+}