1919import net .minecraft .util .text .TextFormatting ;
2020
2121import com .cleanroommc .modularui .api .drawable .IDrawable ;
22+ import com .cleanroommc .modularui .api .drawable .IHoverable ;
2223import com .cleanroommc .modularui .api .drawable .IKey ;
24+ import com .cleanroommc .modularui .api .drawable .IRichTextBuilder ;
25+ import com .cleanroommc .modularui .api .widget .ITooltip ;
2326import com .cleanroommc .modularui .api .widget .IWidget ;
24- import com .cleanroommc .modularui .drawable .text .DynamicKey ;
27+ import com .cleanroommc .modularui .drawable .text .RichText ;
2528import com .cleanroommc .modularui .factory .PosGuiData ;
2629import com .cleanroommc .modularui .screen .ModularPanel ;
30+ import com .cleanroommc .modularui .screen .RichTooltip ;
31+ import com .cleanroommc .modularui .screen .viewport .GuiContext ;
32+ import com .cleanroommc .modularui .theme .WidgetTheme ;
2733import com .cleanroommc .modularui .utils .Alignment ;
2834import com .cleanroommc .modularui .value .sync .BooleanSyncValue ;
2935import com .cleanroommc .modularui .value .sync .IntSyncValue ;
3339import com .cleanroommc .modularui .widget .ScrollWidget ;
3440import com .cleanroommc .modularui .widget .Widget ;
3541import com .cleanroommc .modularui .widget .scroll .VerticalScrollData ;
42+ import com .cleanroommc .modularui .widget .sizer .Area ;
43+ import com .cleanroommc .modularui .widget .sizer .Box ;
3644import com .cleanroommc .modularui .widgets .CycleButtonWidget ;
3745import com .cleanroommc .modularui .widgets .ProgressWidget ;
46+ import com .cleanroommc .modularui .widgets .RichTextWidget ;
3847import com .cleanroommc .modularui .widgets .SlotGroupWidget ;
39- import com .cleanroommc .modularui .widgets .layout .Column ;
4048import com .cleanroommc .modularui .widgets .layout .Flow ;
41- import com .cleanroommc .modularui .widgets .layout .Row ;
42- import it .unimi .dsi .fastutil .ints .Int2ObjectArrayMap ;
43- import it .unimi .dsi .fastutil .ints .Int2ObjectMap ;
4449import org .jetbrains .annotations .NotNull ;
4550import org .jetbrains .annotations .Nullable ;
4651
4752import java .io .IOException ;
4853import java .util .ArrayList ;
4954import java .util .Collections ;
5055import java .util .List ;
56+ import java .util .Objects ;
5157import java .util .function .BiFunction ;
5258import java .util .function .BooleanSupplier ;
5359import java .util .function .Consumer ;
5460import java .util .function .DoubleSupplier ;
55- import java .util .function .Function ;
5661import java .util .function .IntSupplier ;
5762import java .util .function .Supplier ;
5863
64+ import static com .cleanroommc .modularui .api .drawable .IKey .renderer ;
65+
5966public class MultiblockUIFactory {
6067
6168 private final MultiblockWithDisplayBase mte ;
@@ -144,7 +151,7 @@ private Widget<?> createIndicator() {
144151 .pos (174 - 5 , screenHeight - 18 - 3 )
145152 .onUpdateListener (w -> w .overlay (getIndicatorOverlay (builder )))
146153 .tooltip (tooltip -> tooltip .setAutoUpdate (true ))
147- .tooltipBuilder (tooltip -> tooltip . addDrawableLines ( builder . getTextList ()) );
154+ .tooltipBuilder (builder :: buildTooltip );
148155 }
149156
150157 private IDrawable getIndicatorOverlay (Builder builder ) {
@@ -308,27 +315,29 @@ public MultiblockUIFactory customScreen(Supplier<ParentWidget<?>> customScreen)
308315 protected Widget <?> createScreen (PanelSyncManager syncManager ) {
309316 final var builder = builder ();
310317 this .displayText .accept (builder );
311- var col = new Column ();
312- builder .build ( col );
318+ RichTextWidget widget = new RichTextWidget ();
319+ builder .buildDisplay ( widget );
313320 final var compare = builder ();
314321
315322 return new ParentWidget <>()
316323 .child (createIndicator ())
317324 .child (customScreen != null ? customScreen .get () : new ScrollWidget <>(new VerticalScrollData ())
318325 .sizeRel (1f )
319- .child (col .expanded ()
326+ .child (widget .sizeRel (1f )
327+ .alignment (Alignment .TopLeft )
320328 .margin (4 , 4 )
321329 .onUpdateListener (column -> {
322330 // really debating on if the display screen should be its own widget
323- compare .clear ();
331+ // compare.clear();
324332 this .displayText .accept (compare );
325- if (!builder .hasChanged (compare ) && !dirty ) return ;
326- builder .clear ();
327- column .getChildren ().clear ();
328- this .displayText .accept (builder );
329- builder .build (column );
330- resize (column );
331- dirty = false ;
333+ // if (!builder.hasChanged(compare) && !dirty) return;
334+ // builder.clear();
335+ if (builder .hasChanged (compare ))
336+ widget .markDirty ();
337+ // this.displayText.accept(builder);
338+ // builder.build(column);
339+ // resize(column);
340+ // dirty = false;
332341 })))
333342 .background (GTGuiTextures .DISPLAY )
334343 .size (190 , screenHeight )
@@ -465,9 +474,11 @@ protected static Builder builder() {
465474 @ SuppressWarnings ({ "UnusedReturnValue" , "unused" })
466475 public static class Builder {
467476
468- private final List <IDrawable > textList ;
469- private Function <IDrawable , Widget <?>> widgetFunction = Builder ::keyMapper ;
470- private final Int2ObjectMap <IDrawable > tooltips = new Int2ObjectArrayMap <>();
477+ private final RichText text = new RichText ();
478+ private final List <Consumer <IRichTextBuilder <? extends IRichTextBuilder <?>>>> textList = new ArrayList <>();
479+ // private final List<IDrawable> textList;
480+ // private Function<IDrawable, Widget<?>> widgetFunction = Builder::keyMapper;
481+ // private final Int2ObjectMap<IDrawable> tooltips = new Int2ObjectArrayMap<>();
471482
472483 private BooleanSupplier isWorkingEnabled = () -> false ;
473484 private BooleanSupplier isActive = () -> false ;
@@ -479,15 +490,15 @@ public static class Builder {
479490 private IKey runningKey = IKey .lang ("gregtech.multiblock.running" ).format (TextFormatting .GREEN );
480491 private boolean dirty ;
481492
482- protected static Widget <?> keyMapper (IDrawable key ) {
483- return key .asWidget ()
484- .widthRel (1f )
485- .height (12 );
486- }
493+ // protected static Widget<?> keyMapper(IDrawable key) {
494+ // return key.asWidget()
495+ // .widthRel(1f)
496+ // .height(12);
497+ // }
487498
488- private Builder () {
489- this .textList = new ArrayList <>();
490- }
499+ // private Builder() {
500+ // this.textList = new ArrayList<>();
501+ // }
491502
492503 public Builder structureFormed (boolean structureFormed ) {
493504 this .isStructureFormed = structureFormed ;
@@ -672,11 +683,11 @@ public Builder addWorkingStatusLine() {
672683
673684 addKey (KeyUtil .string (() -> {
674685 if (!isWorkingEnabled .getAsBoolean ()) {
675- return TextFormatting . GOLD + pausedKey .get ();
686+ return pausedKey .getFormatted ();
676687 } else if (isActive .getAsBoolean ()) {
677- return TextFormatting . GREEN + runningKey .get ();
688+ return runningKey .getFormatted ();
678689 } else {
679- return TextFormatting . GRAY + idlingKey .get ();
690+ return idlingKey .getFormatted ();
680691 }
681692 }));
682693 return this ;
@@ -881,25 +892,25 @@ public Builder addFuelNeededLine(String fuelName, IntSupplier previousRecipeDura
881892
882893 /** Insert an empty line into the text list. */
883894 public Builder addEmptyLine () {
884- addKey ( IKey . EMPTY ); // this is going to cause problems maybe
895+ this . text . newLine ();
885896 return this ;
886897 }
887898
888899 /** Add custom text dynamically, allowing for custom application logic. */
889- public Builder addCustom (Consumer <List < IDrawable > > customConsumer ) {
890- List <IDrawable > customKeys = new ArrayList <>();
891- customConsumer .accept (customKeys );
892- customKeys .forEach (this ::addKey );
900+ public Builder addCustom (Consumer <RichText > customConsumer ) {
901+ // List<IDrawable> customKeys = new ArrayList<>();
902+ customConsumer .accept (this . text );
903+ // customKeys.forEach(this::addKey);
893904 return this ;
894905 }
895906
896- /**
897- * @param widgetFunction function to build widgets from keys
898- */
899- public Builder widgetFunction (Function <IDrawable , Widget <?>> widgetFunction ) {
900- this .widgetFunction = widgetFunction ;
901- return this ;
902- }
907+ // / **
908+ // * @param widgetFunction function to build widgets from keys
909+ // */
910+ // public Builder widgetFunction(Function<IDrawable, Widget<?>> widgetFunction) {
911+ // this.widgetFunction = widgetFunction;
912+ // return this;
913+ // }
903914
904915 protected boolean isEmpty () {
905916 return textList .isEmpty ();
@@ -909,41 +920,129 @@ protected void clear() {
909920 textList .clear ();
910921 }
911922
912- protected void build (ParentWidget <?> parent ) {
913- for (int i = 0 ; i < textList .size (); i ++) {
914- var line = this .widgetFunction .apply (textList .get (i ));
915- if (tooltips .containsKey (i ))
916- line .addTooltipLine (tooltips .get (i ));
917- parent .child (line );
918- }
923+ protected void buildDisplay (RichTextWidget parent ) {
924+ parent .textBuilder (richText -> this .textList .forEach (t -> t .accept (richText )));
925+ // for (int i = 0; i < textList.size(); i++) {
926+ // var line = this.widgetFunction.apply(textList.get(i));
927+ // if (tooltips.containsKey(i))
928+ // line.addTooltipLine(tooltips.get(i));
929+ // parent.child(line);
930+ // }
919931 }
920932
921- protected List <IDrawable > getTextList () {
922- return Collections .unmodifiableList (textList );
933+ protected void buildTooltip (RichTooltip tooltip ) {
934+ this .textList .forEach (t -> t .accept (tooltip ));
935+ // parent.tooltipBuilder(richText -> this.textList.forEach(t -> t.accept(richText)));
923936 }
924937
925- protected boolean hasChanged (Builder other ) {
926- if (textList .size () != other .textList .size ()) return true ;
927- for (int i = 0 ; i < textList .size (); i ++) {
928- IDrawable left = textList .get (i ), right = other .textList .get (i );
929-
930- // dynamic keys are impossible to check, skip
931- if (left instanceof DynamicKey && right instanceof DynamicKey )
932- continue ;
938+ protected RichText getTextList () {
939+ // return Collections.unmodifiableList(textList);
940+ return this .text ;
941+ }
933942
934- if (!left .equals (right ))
943+ protected boolean hasChanged (Builder other ) {
944+ List <String > cur = text .getStringRepresentation ();
945+ List <String > oth = other .text .getStringRepresentation ();
946+ if (cur .size () != oth .size ()) return true ;
947+ for (int i = 0 ; i < cur .size (); i ++) {
948+ if (!Objects .equals (cur .get (i ), oth .get (i )))
935949 return true ;
936950 }
937951 return false ;
938952 }
939953
940954 private void addKey (IDrawable key ) {
941- this .textList .add (key );
955+ // this.text.add(key);
956+ textList .add (richText -> richText .addLine (key ));
957+ // this.textList.add(key);
942958 }
943959
944960 private void addKey (IDrawable key , IDrawable hover ) {
945- this .tooltips .put (textList .size (), hover );
946- addKey (key );
961+ // this.text.add();
962+ // this.tooltips.put(textList.size(), hover);
963+ // addKey(key.asIcon().asHoverable().addTooltipLine(hover));
964+ addKey (new TestDrawable (key , hover ));
965+ }
966+ }
967+
968+ private static class TestDrawable implements IHoverable , ITooltip <TestDrawable > {
969+
970+ private final IDrawable drawable ;
971+ private RichTooltip tooltip ;
972+ private final Area area ;
973+
974+ private TestDrawable (IDrawable drawable , IDrawable hover ) {
975+ this .drawable = drawable ;
976+ this .area = drawable instanceof IKey key ? calculateArea (key ) : new Area ();
977+ tooltip ().addLine (hover );
978+ }
979+
980+ private Area calculateArea (IKey key ) {
981+ renderer .setSimulate (true );
982+ renderer .setScale (1f );
983+ renderer .draw (key .getFormatted ());
984+ renderer .getMaxWidth (Collections .singletonList (key .getFormatted ()));
985+ int h = (int ) renderer .getLastWidth ();
986+ int w = (int ) renderer .getLastHeight ();
987+ renderer .setSimulate (false );
988+ return new Area (0 , 0 , w , h );
989+ }
990+
991+ @ Override
992+ public void setRenderedAt (int x , int y ) {
993+ this .area .setPos (x , y );
994+ }
995+
996+ @ Override
997+ public Area getRenderedArea () {
998+ return this .area ;
999+ }
1000+
1001+ @ Override
1002+ public int getWidth () {
1003+ return this .area .w ();
1004+ }
1005+
1006+ @ Override
1007+ public int getHeight () {
1008+ return this .area .h ();
1009+ }
1010+
1011+ @ Override
1012+ public Box getMargin () {
1013+ return this .area .getMargin ();
1014+ }
1015+
1016+ @ Override
1017+ @ Nullable
1018+ public RichTooltip getTooltip () {
1019+ return tooltip ;
1020+ }
1021+
1022+ @ Override
1023+ public @ NotNull RichTooltip tooltip () {
1024+ if (this .tooltip == null ) this .tooltip = new RichTooltip (area -> area .set (getRenderedArea ()));
1025+ return tooltip ;
1026+ }
1027+
1028+ @ Override
1029+ public TestDrawable tooltip (RichTooltip tooltip ) {
1030+ this .tooltip = tooltip ;
1031+ return this ;
1032+ }
1033+
1034+ @ Override
1035+ public void draw (GuiContext context , int x , int y , int width , int height , WidgetTheme widgetTheme ) {
1036+ if (drawable instanceof IKey key ) {
1037+ renderer .setColor (widgetTheme .getTextColor ());
1038+ renderer .setShadow (widgetTheme .getTextShadow ());
1039+ renderer .setAlignment (Alignment .CenterLeft , width , height );
1040+ renderer .setScale (1f );
1041+ renderer .setPos (x , y );
1042+ renderer .draw (key .getFormatted ());
1043+ } else {
1044+ drawable .draw (context , x , y , width , height , widgetTheme );
1045+ }
9471046 }
9481047 }
9491048}
0 commit comments