// background color is set with setBackground sclass JMultiColorBar > JComponentWithChangeListeners { class Entry { // absolute value from the left! settable double value; settable Color color; settable S text; settable S toolTip; Entry previous() { ret elementBefore(entries, this); } double relativeValue() { Entry p = previous(); ret p == null ? value : value-p.value; } } L entries = notifyingList(l0 repaint); settableWithVar double max = 100; settable L defaultColors = ll(Color.red, Color.blue); InstantNeverHideToolTip toolTipMaker; swappable Color defaultColor(int index) { ret getCyclic(defaultColors, index); } Entry makeEntry(double relativeValue) { Entry prev = last(entries); double value = prev == null ? relativeValue : relativeValue+prev.value; ret new Entry().+value.color(defaultColor(l(entries))); } Entry addEntry aka add(S text, double relativeValue) { ret addAndReturn(entries, makeEntry(relativeValue).+text); } Entry addEntry aka add(double relativeValue, Color color) { ret addAndReturn(entries, makeEntry(relativeValue).+color); } S toolTipForEntry(Entry e) { ret e == null ?: spaceCombine(or2(e.toolTip, e.text), renderValue(e.relativeValue())); } swappable S renderValue(double value) { ret str(value); } scaffolded S toolTipForPosition(Pt p) { int w = getWidth(); Entry e = firstThat(entries, _e -> p.x < xForEntry(_e, w)); if (scaffolded()) printVars(+e, xs := map(entries, _e -> xForEntry(_e, w))); ret toolTipForEntry(e); } *() { varMax().onChange(l0 repaint); jMinSize(50, 10, this); toolTipMaker = new InstantNeverHideToolTip(l1 toolTipForPosition, this); } int xForEntry(Entry e, int w) { ret iround(w*clampZeroToOne(doubleRatio(e.value, max))); } public void paintComponent(Graphics g) { super.paintComponent(g); // paint background int w = getWidth(), h = getHeight(); int x = 0; for (e : entries) { int x2 = main max(x, xForEntry(e, w)); if (x2 > x) fillRect(g, x+1, 0, x2-x, h, e.color); x = x2; } } }