Lemur Layout Question


#1

I need some advice with setting a layout.

I have a textfield and i would like to attach a slider to its east boarder. I would like to reuse the construct. Thus I have a class that extends textfield. I call that new class like

  ViewField vF = new ViewField("Test",id, "OSG");
  guiNode.attachChild(vF);         

In this class I call

 layout = new BorderLayout();
 this.getControl(GuiControl.class).setLayout(layout);
 layout.addChild(slidervert, BorderLayout.Position.East);

unfortunately the result looks like this

even if I change the code to

  SpringGridLayout layout2 = new SpringGridLayout( Axis.X, Axis.Y, FillMode.None, FillMode.None);
     this.getControl(GuiControl.class).setLayout(layout2);
     layout2.addChild(0,2,slidervert);

I am getting the same result.
I know if i would do something like

 SpringGridLayout layout3 = new SpringGridLayout( Axis.X, Axis.Y, FillMode.None, FillMode.None);
  layout3.addChild(0,1,this);
 layout3.addChild(0,2,slidervert);
 Container con= new Container(layout3);
 lGuiNode.attachChild(con);      

it might work, but I dont like to create a Container as I have no GuiNode inside my class and I may loose all the functionality of textfield if i hand over the container.

So my question is - how can I make the slider be attached to the side of textfield and not still inside textfield? I have tried with an inset but it did not work for me.

I have used the same approach to attach a horizontal slider to listbox (by copying from the vertical slider) and wonder why it is not working here.

edit: wrong category


#2

What does ViewField extend? TextField?

…that’s probably not going to work very well as TextField already “is-a” TextField and doesn’t know how to act like a layout container.

I believe ListBox already is a layout container and so it works there. (Yep… just looked.)

(And when I say “layout container” here, I don’t mean “extends Container”… just that it has a layout and organizes itself accordingly.) For example, ListBox manages all of its children separately. It is effectively a container.

I guess you want something that is-a TextField but also has a scroll bar on the side. This is going to be tricky (and would be tricky in pretty much any lib, Swing, etc.) Because the “text field” functionality is innate to the element itself and doesn’t want to be shoved aside. You technically can do it (and you could in Swing, too… with a LOT of work)… but you are going to end up with something that very much looks like you extended TextField and then contain another TextField.

Is being a subclass of TextField important or is it just important to have setText()/getText()? That might help me point out the optimal path.


#3

My idea was to call - in that case - the Viewfield, that is nothing more then a Textfield with a slider attached I also was thinking to put the slider handling in that ViewField.

Once I have done this I could reuse my textfield with slider and all functionality again and again without the need to rewrite the slider code.

  @Override
    public void updateLogicalState( float tpf ) {
        super.updateLogicalState(tpf);
        if (vFmodelref.update()) {
            ... react to the slider value change
        }

#4

I may need to add, that I was planning to use this like your wordwrap example. My textfield allows scrolling, multiline (e.g. you have 10 lines and only 5 are shown at the same time) and it is autoadjusting the line lenght to the given text. I also have the textselect etc. here.
I have not yet looked to the wordwrap example but my idea was if I have info text that is very long I display it in a modified textfield where most key mappings (except e.g. the select all, the scrolling by mouse and keys) are deleted and I can reuse the scrolling option that I already have.

Like on left click on a item you get a info text and if it is to long you can scroll inside that text. I just dont like to redo this for all kind of items


#5

I feel like you may not have answered my question… or that I may not have understood that answer.

Are you trying to make:

public class ViewField extend TextField?
   ... do a bunch of complicated things

Or are you ok with:

public class ViewField extends Panel (or Container)
    private TextField textField;
    private Slider slider;

....do some simple things.

Because the second way is super easy and the first way would be super hard in most GUI libraries.


#6

Maybe I have not understood the question.
But I have the feeling that the second approach is what I am looking for.
Its the same approach you have used for Listbox.
It may take some time but I will work on that and give a short feedback here.


#7

Let me know if you need any additional guidance.


#8

I started, result:

Cool thing is by using my own ElementId I can later set the styling for slider and textfield in my new element separately (e.g. textfields with font x and textfield inside element with font y, same for the slider).

I used the following approach copied from listbox, that I will now adjust for my needs.

import com.simsilica.lemur.*;
import com.simsilica.lemur.component.BorderLayout;
import com.simsilica.lemur.core.GuiControl;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import com.simsilica.lemur.text.DocumentModel;


public class ReadField extends Panel {

    public static final String ELEMENT_ID = "readfield";
    public static final String CONTAINER_ID = "container";
    private BorderLayout layout;
    private VersionedReference<DocumentModel> vFmodelref;

    private RangedValueModel baseIndex;
    private VersionedReference<Double> sliderref;


    public TextField getTextfield() {
        return tf;
    }

    public TextField tf;

    private Slider slidervert;
    public static final String SLIDER_ID = "slider";


    public ReadField() {
        this(true, new ElementId(ELEMENT_ID),null);
    }

    protected ReadField(boolean applyStyles, ElementId elementId, String style) {
        super(false, elementId.child(CONTAINER_ID), style);

        this.layout = new BorderLayout();
        getControl(GuiControl.class).setLayout(layout);


        // create textfield and reference
        tf = new TextField("Test");
        vFmodelref = tf.getDocumentModel().createReference();

        layout.addChild(tf, BorderLayout.Position.Center);


        // create slider and reference
        baseIndex = new DefaultRangedValueModel();
        sliderref = baseIndex.createReference();
        baseIndex.setMaximum(10);
        baseIndex.setValue(4);
        slidervert = new Slider(baseIndex, Axis.Y,  elementId.child(SLIDER_ID), this.getStyle());

        layout.addChild(slidervert,BorderLayout.Position.East);
    }


    @Override
    public void updateLogicalState( float tpf ) {
        super.updateLogicalState(tpf);
        if (vFmodelref.update()) {
            // ToDo Textfield changed
        }
        if (sliderref.update()) {
            // ToDo slider was changed
        }

    }
}


#9

Nice.

Note: you mention making your stuff more easily stylable and you’ve done a lot for that already. I noticed you missed giving the text field an element ID.

Probably you want:
tf = new TextField(“Test”, elementId.child(TextField.ELEMENT_ID));

…then it will pick up any standard text field styling but also be customizable under “readfield.textField”