Skip to content

Commit

Permalink
Initial read-only text area
Browse files Browse the repository at this point in the history
Affects: #14
  • Loading branch information
io7m committed Nov 25, 2023
1 parent 646ca4f commit c225d6f
Show file tree
Hide file tree
Showing 21 changed files with 1,242 additions and 13 deletions.
Expand Up @@ -31,6 +31,7 @@
import com.io7m.jsycamore.api.windows.SyWindowViewportAccumulatorType;
import com.io7m.jtensors.core.parameterized.vectors.PVector2I;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Predicate;
Expand Down Expand Up @@ -119,6 +120,20 @@ Optional<SyComponentType> componentForWindowRelative(
SyWindowViewportAccumulatorType context,
SyComponentQuery query);

/**
* A convenience function to remove all child components of this component.
*/

default void childrenClear()
{
final var children =
List.copyOf(this.node().children());

for (final var child : children) {
this.node().childRemove(child);
}
}

/**
* A convenience function to add a component as a child of this component.
*
Expand Down
Expand Up @@ -16,6 +16,7 @@

package com.io7m.jsycamore.api.components;

import com.io7m.jattribute.core.AttributeReadableType;
import com.io7m.jsycamore.api.themes.SyThemeClassNameType;

import java.util.List;
Expand All @@ -34,4 +35,10 @@ default List<SyThemeClassNameType> themeClassesDefaultForComponent()
{
return List.of(TEXT_AREA);
}

/**
* @return The text sections within the area
*/

AttributeReadableType<List<String>> textSections();
}
Expand Up @@ -23,5 +23,11 @@
public interface SyTextAreaType
extends SyTextAreaReadableType, SyComponentType
{
/**
* Append a text section to the end of the text area.
*
* @param section The section
*/

void textSectionAppend(String section);
}
Expand Up @@ -16,6 +16,8 @@

package com.io7m.jsycamore.api.text;

import java.util.List;

/**
* A font.
*/
Expand Down Expand Up @@ -55,4 +57,35 @@ public interface SyFontType
*/

SyFontDescription description();

/**
* Split the given text into lines based on the given wrapping width.
*
* @param text The text
* @param width The width
*
* @return The split lines
*/

List<SyTextSectionLineType> textLayout(
String text,
int width);

/**
* Split the given texts into lines based on the given wrapping width.
*
* @param texts The texts
* @param width The width
*
* @return The split lines
*/

default List<SyTextSectionLineType> textLayoutMultiple(
final List<String> texts,
final int width)
{
return texts.stream()
.flatMap(s -> this.textLayout(s, width).stream())
.toList();
}
}
@@ -0,0 +1,41 @@
/*
* Copyright © 2023 Mark Raynsford <code@io7m.com> https://www.io7m.com
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/


package com.io7m.jsycamore.api.text;

import com.io7m.jregions.core.parameterized.sizes.PAreaSizeI;
import com.io7m.jsycamore.api.spaces.SySpaceParentRelativeType;

/**
* A line that has been produced by splitting a text section into multiple lines
* based on a wrapping width.
*/

public interface SyTextSectionLineType
{
/**
* @return The size of the text line
*/

PAreaSizeI<SySpaceParentRelativeType> size();

/**
* @return The actual line text
*/

String text();
}
Expand Up @@ -17,11 +17,19 @@

package com.io7m.jsycamore.awt.internal;

import com.io7m.jregions.core.parameterized.sizes.PAreaSizeI;
import com.io7m.jsycamore.api.spaces.SySpaceParentRelativeType;
import com.io7m.jsycamore.api.text.SyFontDescription;
import com.io7m.jsycamore.api.text.SyFontType;
import com.io7m.jsycamore.api.text.SyTextSectionLineType;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
Expand Down Expand Up @@ -80,4 +88,65 @@ public SyFontDescription description()
{
return this.description;
}

@Override
public List<SyTextSectionLineType> textLayout(
final String text,
final int width)
{
Objects.requireNonNull(text, "text");

if (text.isEmpty()) {
return List.of(
new SectionLine(PAreaSizeI.of(0, this.textHeight()), "")
);
}

final var attributedString = new AttributedString(text);
attributedString.addAttribute(TextAttribute.FONT, this.font);

final var breaker =
new LineBreakMeasurer(
attributedString.getIterator(),
this.metrics.getFontRenderContext()
);

final var fWidth = (float) width;

var indexThen = 0;

final var results =
new LinkedList<SyTextSectionLineType>();

while (true) {
final var layout = breaker.nextLayout(fWidth);
if (layout == null) {
break;
}

final var indexNow =
breaker.getPosition();
final var bounds =
layout.getBounds();

final var line =
new SectionLine(
PAreaSizeI.of((int) Math.ceil(bounds.getWidth()), this.textHeight()),
text.substring(indexThen, indexNow)
);

results.add(line);
indexThen = indexNow;
}

return results;
}

private record SectionLine(
PAreaSizeI<SySpaceParentRelativeType> size,
String text)
implements SyTextSectionLineType
{

}
}

0 comments on commit c225d6f

Please sign in to comment.