// background color is set with setBackground sclass JMultiColorBar > JComponentWithChangeListeners { class Entry { settable double value; settable Color color; settable S text; settable S toolTip; } 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 addEntry aka add(S text, double value) { ret addAndReturn(entries, new Entry().+text.+value.color(defaultColor(l(entries)))); } Entry addEntry aka add(double value, Color color) { ret addAndReturn(entries, new Entry().+value.+color); } S toolTipForEntry(Entry e) { ret e == null ?: spaceCombine(or2(e.toolTip, e.text), str(e.value)); } scaffolded S toolTipForPosition(Pt p) { int w = getWidth(); Entry e = lastThat(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; } } }