Home > OS >  Make status trimbar contribution when its content changes
Make status trimbar contribution when its content changes

Time:10-01

I'm trying to add an Eclipse status trimbar contribution where the contents of the contribution (i.e., child elements' text) dynamically change. Note that I'm not trying to add "line, column" information into the status bar.

Ideally, the contribution's width should adapt to the width of its contents, a bit like what happens in VSCode:

enter image description here enter image description here

However, if that isn't easily feasible, an acceptable alternative would be to have a "fixed" width for the status trimbar, or even a fixed width for each individual child (since I don't intend to have children appearing and disappearing).

Below is what I've tried. How do you think I should do this if nothing I've tried for the past 2 days worked?

In case you think the problem might actually be an Eclipse bug, note that I'm using Eclipse version 2021-06 (4.20.0) on Linux.


What I have tried

I have this in plugin.xml:

<extension
    point="org.eclipse.ui.menus">
    <menuContribution
        locationURI="toolbar:org.eclipse.ui.trim.status">
        <toolbar
            id="some.package.StatusTrimBarContribution">
            <control
                class="some.package.StatusTrimBarContribution">
            </control>
        </toolbar>
    </menuContribution>
</extension>

I've tried doing this in at least 4 different ways. As a reference, here is the class StatusTrimBarContribution:

public class StatusTrimBarContribution extends WorkbenchWindowControlContribution {
    // A
    private static String currText = /* see below */;

    private Label m_lbl = null;
    private Label m_lbl2 = null;
    private Control m_root = null;

    public StatusTrimBarContribution() {
        // Register to String event
    }

    @Override
    public void dispose() {
        // Unregister from String event
    }

    @Override
    protected Control createControl(Composite parent) {
        // B
    }

    @Subscribe // From guava
    private void someEventHandler(String event) {
        currText = "lp_much_longer";
        if (m_lbl != null) {
            m_lbl.setText();
            m_root.getParent().requestLayout();
        }
    }
}

Attempt #1

In this attempt we add an intermediary Composite between the labels and parent, we use a GridLayout on the intermediary, and we add a GridData into m_lbl.

// A
private static String currText = "empty";

// B
@Override
protected Control createControl(Composite parent) {
    GridLayout gl = new GridLayout(2, false);
    Composite comp = new Composite(parent, SWT.NONE);
    comp.setLayout(gl);
    m_lbl = new Label(comp, SWT.RIGHT);
    m_lbl.setText(currText);
    GridDataFactory.defaultsFor(m_lbl).hint(200, SWT.DEFAULT).applyTo(m_lbl);
    m_lbl2 = new Label(comp, SWT.RIGHT);
    m_lbl2.setText("lbl2");
    m_root = comp;
    return comp;
}

The result is that the labels are too tall and get truncated. Note that I've also tried setting the margin height to 0, and, while it's better than below, the labels would still get truncated.

enter image description here

Attempt #2

Compared to #1, we remove the intermediary Composite, and instead use the layout directly on parent. Also, we remove the GridData, because, at this point, why not.

// A
private static String currText = "empty";

// B
@Override
protected Control createControl(Composite parent) {
    GridLayout gl = new GridLayout(2, false);
    parent.setLayout(gl);
    m_lbl = new Label(parent, SWT.RIGHT);
    m_lbl.setText(currText);
    m_lbl2 = new Label(parent, SWT.RIGHT);
    m_lbl2.setText("lbl2");
    m_root = m_lbl;
    return m_lbl;
}

The result is the same as before, except, additionally, that m_lbl is not large enough to hold the text:

enter image description here

Attempt #3

Compared to #2, we additionally remove the layout.

// A
private static String currText = "empty";

// B
@Override
protected Control createControl(Composite parent) {
    m_lbl = new Label(parent, SWT.RIGHT);
    m_lbl.setText(currText);
    m_lbl2 = new Label(parent, SWT.RIGHT);
    m_lbl2.setText("lbl2");
    m_root = m_lbl;
    return m_lbl;
}

The labels are no longer too tall, however, the width of the labels is still to small for the text:

enter image description here

Attempt #4

Compared to #3, we initially assign a very long string into m_lbl.

// A
// Yes, this is ridiculous
private static String currText = " ".repeat(60);

// B
@Override
protected Control createControl(Composite parent) {
    m_lbl = new Label(parent, SWT.RIGHT);
    m_lbl.setText(currText);
    m_lbl2 = new Label(parent, SWT.RIGHT);
    m_lbl2.setText("lbl2");
    m_root = m_lbl;
    return m_lbl;
}

The result is that both labels are completely visible, but now m_lbl2 has the same width as m_lbl, which is far more than I want. Plus, if the user's font is different from mine, the width of the labels might become too large or too small due to the initial string.

enter image description here

CodePudding user response:

Using the minimum width setting of GridData works for me:

  @Override
  protected Control createControl(final Composite parent)
  {
    final Composite comp = new Composite(parent, SWT.NONE);
    GridLayoutFactory.fillDefaults().numColumns(2).applyTo(comp);

    m_lbl = new Label(comp, SWT.RIGHT);
    m_lbl.setText("label 1");

    GridDataFactory.fillDefaults().grab(true, false).minSize(200, SWT.DEFAULT).applyTo(m_lbl);

    m_lbl2 = new Label(comp, SWT.RIGHT);
    m_lbl2.setText("lbl2");

    GridDataFactory.fillDefaults().grab(true, false).minSize(100, SWT.DEFAULT).applyTo(m_lbl2);

    m_root = comp;

    return comp;
  }

Note: Changing the layout of parent is against the rules, it could damage the layout of other components.

  • Related