Skip to content

Commit

Permalink
Add <SubPages /> tag and document it. (#7326)
Browse files Browse the repository at this point in the history
Fixes #7195
  • Loading branch information
shartte committed Aug 9, 2023
1 parent 172a36d commit 4375421
Show file tree
Hide file tree
Showing 31 changed files with 358 additions and 78 deletions.
11 changes: 11 additions & 0 deletions guidebook.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ To automatically show a table of contents for a category, use the `<CategoryInde
and specify the name of the category. It will then display a list of all pages that declare to be part of that
category.

#### Sub Pages

This tag will show a list of links to pages. The list will be sourced from the child-pages of
the current page in the navigation-tree. If a specific page-id is given in the `id` attribute, the child-pages of that
page will be shown instead.

The list can be sorted alphabetically (by title) by adding `alphabetical={true}`.

To show the icons associated with each navigation-node, supply `icons={true}`. This does not look very appealing if
some child-pages have icons and others don't.

#### Item Images

To show an item, use:
Expand Down
15 changes: 1 addition & 14 deletions guidebook/ae2-mechanics/ae2-mechanics-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,4 @@ navigation:

# AE2 Mechanics

* [Autocrafting](autocrafting.md)
* [Bytes and Types](bytes-and-types.md)
* [Cable Subparts](cable-subparts.md)
* [Certus Growth](certus-growth.md)
* [Channels](channels.md)
* [Devices](devices.md)
* [Energy](energy.md)
* [Import, Export, and Storage](import-export-storage.md)
* [Meteorites](meteorites.md)
* [Network Connections](me-network-connections.md)
* [P2P Tunnels](../items-blocks-machines/p2p_tunnels.md)
* [Quantum Bridge](../items-blocks-machines/quantum_bridge.md)
* [Spatial IO](spatial-io.md)
* [Subnetworks](subnetworks.md)
<SubPages />
7 changes: 0 additions & 7 deletions guidebook/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,3 @@ quantities of items in stock, crafting more as needed, or simply transfer items
* [AE2 Mechanics](ae2-mechanics/ae2-mechanics-index.md)
* [Example Setups](example-setups/example-setups-index.md)
* [Items, Blocks, and Machines](items-blocks-machines/items-blocks-machines-index.md)

[AE2 GitHub](https://github.com/AppliedEnergistics/Applied-Energistics-2)

<GameScene zoom="4" interactive={true}>
<ImportStructure src="assets/assemblies/autocraft_setup_greebles.snbt" />
<IsometricCamera yaw="195" pitch="30" />
</GameScene>
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static void parseLink(PageCompiler compiler, String href, Visitor visitor
// Determine the page id, account for relative paths
ResourceLocation pageId;
try {
pageId = IdUtils.resolveLink(uri.getPath(), compiler.getId());
pageId = IdUtils.resolveLink(uri.getPath(), compiler.getPageId());
} catch (ResourceLocationException ignored) {
visitor.handleError("Invalid link");
return;
Expand Down
20 changes: 11 additions & 9 deletions src/main/java/appeng/client/guidebook/compiler/PageCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import java.util.Map;
import java.util.Objects;

import javax.swing.plaf.nimbus.State;

import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -96,7 +94,7 @@ public final class PageCompiler {
private final PageCollection pages;
private final ExtensionCollection extensions;
private final String sourcePack;
private final ResourceLocation id;
private final ResourceLocation pageId;
private final String pageContent;

private final Map<String, TagCompiler> tagCompilers = new HashMap<>();
Expand All @@ -105,12 +103,13 @@ public final class PageCompiler {
// compilers to communicate with each other within the current page.
private final Map<State<?>, Object> compilerState = new IdentityHashMap<>();

public PageCompiler(PageCollection pages, ExtensionCollection extensions, String sourcePack, ResourceLocation id,
public PageCompiler(PageCollection pages, ExtensionCollection extensions, String sourcePack,
ResourceLocation pageId,
String pageContent) {
this.pages = pages;
this.extensions = extensions;
this.sourcePack = sourcePack;
this.id = id;
this.pageId = pageId;
this.pageContent = pageContent;

// Index available tag-compilers
Expand Down Expand Up @@ -400,7 +399,7 @@ private LytImage compileImage(MdAstImage astImage) {
image.setTitle(astImage.title);
image.setAlt(astImage.alt);
try {
var imageId = IdUtils.resolveLink(astImage.url, id);
var imageId = IdUtils.resolveLink(astImage.url, pageId);
var imageContent = pages.loadAsset(imageId);
if (imageContent == null) {
LOGGER.error("Couldn't find image {}", astImage.url);
Expand Down Expand Up @@ -457,11 +456,14 @@ public LytFlowContent createErrorFlowContent(String text, UnistNode child) {
}

public ResourceLocation resolveId(String idText) {
return IdUtils.resolveId(idText, id.getNamespace());
return IdUtils.resolveId(idText, pageId.getNamespace());
}

public ResourceLocation getId() {
return id;
/**
* Get the current page id.
*/
public ResourceLocation getPageId() {
return pageId;
}

public PageCollection getPageCollection() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ protected void compile(PageCompiler compiler, LytFlowParent parent, MdxJsxElemen
image.setTitle(title);
}
try {
var imageId = IdUtils.resolveLink(src, compiler.getId());
var imageId = IdUtils.resolveLink(src, compiler.getPageId());
var imageContent = compiler.loadAsset(imageId);
if (imageContent == null) {
LOGGER.error("Couldn't find image {}", src);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public void compile(PageCompiler compiler, LytFlowParent parent, MdxJsxElementFi
var linksTo = compiler.getIndex(ItemIndex.class).get(id);
// We'll error out for item-links to our own mod because we expect them to have a page
// while we don't have pages for Vanilla items or items from other mods.
if (linksTo == null && id.getNamespace().equals(compiler.getId().getNamespace())) {
if (linksTo == null && id.getNamespace().equals(compiler.getPageId().getNamespace())) {
parent.append(compiler.createErrorFlowContent("No page found for item " + id, el));
return;
}
Expand All @@ -37,7 +37,7 @@ public void compile(PageCompiler compiler, LytFlowParent parent, MdxJsxElementFi

// If the item link is already on the page we're linking to, replace it with an underlined
// text that has a tooltip.
if (linksTo == null || linksTo.anchor() == null && compiler.getId().equals(linksTo.pageId())) {
if (linksTo == null || linksTo.anchor() == null && compiler.getPageId().equals(linksTo.pageId())) {
var span = new LytTooltipSpan();
span.modifyStyle(style -> style.italic(true));
span.appendComponent(stack.getHoverName());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package appeng.client.guidebook.compiler.tags;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import net.minecraft.resources.ResourceLocation;

import appeng.client.guidebook.PageAnchor;
import appeng.client.guidebook.compiler.PageCompiler;
import appeng.client.guidebook.document.block.AlignItems;
import appeng.client.guidebook.document.block.LytBlock;
import appeng.client.guidebook.document.block.LytBlockContainer;
import appeng.client.guidebook.document.block.LytHBox;
import appeng.client.guidebook.document.block.LytList;
import appeng.client.guidebook.document.block.LytListItem;
import appeng.client.guidebook.document.block.LytParagraph;
import appeng.client.guidebook.document.flow.LytFlowLink;
import appeng.client.guidebook.navigation.NavigationNode;
import appeng.client.guidebook.scene.LytItemImage;
import appeng.libs.mdast.mdx.model.MdxJsxElementFields;

public class SubPagesCompiler extends BlockTagCompiler {
private static final Comparator<NavigationNode> ALPHABETICAL_COMPARATOR = Comparator
.comparing(NavigationNode::title);

@Override
public Set<String> getTagNames() {
return Set.of("SubPages");
}

@Override
protected void compile(PageCompiler compiler, LytBlockContainer parent, MdxJsxElementFields el) {
var pageIdStr = el.getAttributeString("id", null);
var showIcons = MdxAttrs.getBoolean(compiler, parent, el, "icons", false);
var alphabetical = MdxAttrs.getBoolean(compiler, parent, el, "alphabetical", false);

var navigationTree = compiler.getPageCollection().getNavigationTree();

// Find the page in the tree, if it's explicitly set to empty, show the root nav
List<NavigationNode> subNodes;
if ("".equals(pageIdStr)) {
subNodes = navigationTree.getRootNodes();
} else {
ResourceLocation pageId;
try {
pageId = pageIdStr == null ? compiler.getPageId() : compiler.resolveId(pageIdStr);
} catch (Exception e) {
parent.appendError(compiler, "Invalid id", el);
return;
}

var node = navigationTree.getNodeById(pageId);
if (node == null) {
parent.appendError(compiler, "Couldn't find page " + pageId + " in the navigation tree", el);
return; // Not found in navigation tree
}

subNodes = node.children();
}

if (alphabetical) {
subNodes = new ArrayList<>(subNodes);
subNodes.sort(ALPHABETICAL_COMPARATOR);
}

var list = new LytList(false, 0);
for (var childNode : subNodes) {
if (!childNode.hasPage()) {
continue;
}

var listItem = new LytListItem();
var listItemPar = new LytParagraph();

var link = new LytFlowLink();
link.setClickCallback(guideScreen -> guideScreen.navigateTo(PageAnchor.page(childNode.pageId())));
link.appendText(childNode.title());
listItemPar.append(link);

LytBlock listItemBlock = listItemPar;

if (showIcons && !childNode.icon().isEmpty()) {
var lytHBox = new LytHBox();

var icon = new LytItemImage();
icon.setItem(childNode.icon());
lytHBox.append(icon);
lytHBox.append(listItemPar);
lytHBox.setAlignItems(AlignItems.CENTER);
listItemBlock = lytHBox;
}

listItem.append(listItemBlock);
list.append(listItem);
}
parent.append(list);
}
}
5 changes: 5 additions & 0 deletions src/main/java/appeng/client/guidebook/document/LytRect.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package appeng.client.guidebook.document;

import org.joml.Matrix4f;
import org.joml.Vector2i;
import org.joml.Vector3f;

public record LytRect(int x, int y, int width, int height) {
Expand Down Expand Up @@ -113,4 +114,8 @@ public LytRect transform(Matrix4f pose) {
public LytSize size() {
return new LytSize(width, height);
}

public Vector2i point() {
return new Vector2i(x, y);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package appeng.client.guidebook.document.block;

public enum AlignItems {
CENTER,
START,
END
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package appeng.client.guidebook.document.block;

public enum LytAxis {
HORIZONTAL,
VERTICAL
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package appeng.client.guidebook.document.block;

/**
* A box that just aligns its content along the vertical or horizontal axis.
*/
public abstract class LytAxisBox extends LytBox {
private int gap;

private AlignItems alignItems = AlignItems.START;

public AlignItems getAlignItems() {
return alignItems;
}

public void setAlignItems(AlignItems alignItems) {
this.alignItems = alignItems;
}

public int getGap() {
return gap;
}

public void setGap(int gap) {
this.gap = gap;
}
}
30 changes: 30 additions & 0 deletions src/main/java/appeng/client/guidebook/document/block/LytBlock.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package appeng.client.guidebook.document.block;

import org.joml.Vector2i;

import net.minecraft.client.renderer.MultiBufferSource;

import appeng.client.guidebook.document.LytRect;
Expand All @@ -26,6 +28,15 @@ public boolean isCulled(LytRect viewport) {
return !viewport.intersects(bounds);
}

public final void setLayoutPos(Vector2i point) {
var deltaX = point.x - bounds.x();
var deltaY = point.y - bounds.y();
if (deltaX != 0 || deltaY != 0) {
bounds = bounds.withX(point.x).withY(point.y);
onLayoutMoved(deltaX, deltaY);
}
}

public final LytRect layout(LayoutContext context, int x, int y, int availableWidth) {
bounds = computeLayout(context, x, y, availableWidth);
return bounds;
Expand Down Expand Up @@ -63,8 +74,27 @@ public void setMarginBottom(int marginBottom) {
this.marginBottom = marginBottom;
}

public int getMarginStart(LytAxis axis) {
return switch (axis) {
case HORIZONTAL -> getMarginLeft();
case VERTICAL -> getMarginTop();
};
}

public int getMarginEnd(LytAxis axis) {
return switch (axis) {
case HORIZONTAL -> getMarginRight();
case VERTICAL -> getMarginBottom();
};
}

protected abstract LytRect computeLayout(LayoutContext context, int x, int y, int availableWidth);

/**
* Implement to react to layout previously computed by {@link #computeLayout} being moved.
*/
protected abstract void onLayoutMoved(int deltaX, int deltaY);

public abstract void renderBatch(RenderContext context, MultiBufferSource buffers);

public abstract void render(RenderContext context);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ protected final LytRect computeLayout(LayoutContext context, int x, int y, int a
return innerLayout.expand(paddingLeft, paddingTop, paddingRight, paddingBottom);
}

@Override
protected void onLayoutMoved(int deltaX, int deltaY) {
for (var child : children) {
child.setLayoutPos(child.bounds.point().add(deltaX, deltaY));
}
}

public final void setPadding(int padding) {
paddingLeft = padding;
paddingTop = padding;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ private Layout createLayout(LayoutContext context, int availableWidth) {
5,
5,
5,
0);
0,
AlignItems.START);

return new Layout(availableWidth, bounds.height());
}
Expand Down
Loading

0 comments on commit 4375421

Please sign in to comment.