@Override MapRects calcMap(final MapRect r, final MapList ml, final int ns, final int ne) { // stores all calculated rectangles final MapRects rects = new MapRects(); // node iterator int ni = ns; // first node of current row int start = ns; // setting initial proportions final double yy = r.y; final double hh = r.h; double xx = r.x; double ww = r.w; MapRects row = new MapRects(); int width; double weight = 0; double sumweight = 1; double tmpratio; double rowratio = Double.MAX_VALUE; while (ni <= ne && xx + ww <= r.x + r.w && yy + hh <= r.y + r.h) { weight += ml.weight[ni]; width = (int) (weight / sumweight * ww); width = width > 0 ? width : 1; final MapRects tmp = new MapRects(); double y = yy; for (int i = start; i <= ni; ++i) { int h = i == ni ? (int) (yy + hh - y) : (int) (ml.weight[i] / weight * hh); h = h > 0 ? h : 1; if (yy <= yy + hh) tmp.add(new MapRect((int) xx, (int) y, width, h, ml.get(i), r.level)); else break; y += h; } tmpratio = lineRatio(tmp); // if ar has increased discard tmp and add row if (tmpratio > rowratio) { // add rects of row to solution rects.add(row); rowratio = Double.MAX_VALUE; // preparing next line ww -= row.get(0).w; xx += row.get(0).w; tmp.reset(); row.reset(); start = ni; sumweight -= weight - ml.weight[ni]; weight = 0; // sometimes there has to be one rectangles to fill the left space if (ne == ni) { row.add(new MapRect((int) xx, (int) yy, (int) ww, (int) hh, ml.get(ni), r.level)); break; } } else { row = tmp; rowratio = tmpratio; ++ni; } } // adding last row for (final MapRect rect : row) rect.w = (int) ww; rects.add(row); return rects; }
@Override void drawRectangles(final Graphics g, final MapRects rects, final float scale) { // some additions to set up borders final MapRect l = view.layout.layout; l.x = (int) scale * l.x; l.y = (int) scale * l.y; l.w = (int) scale * l.w; l.h = (int) scale * l.h; final int ww = view.getWidth(); final int hh = view.getWidth(); final Data data = view.gui.context.data(); final int fsz = GUIConstants.fontSize; final int off = gopts.get(GUIOptions.MAPOFFSETS); final int rs = rects.size; for (int ri = 0; ri < rs; ++ri) { // get rectangle information final MapRect r = rects.get(ri); final int pre = r.pre; // level 1: next context node, set marker pointer to 0 final int lvl = r.level; final boolean full = r.w == ww && r.h == hh; Color col = color(rects, ri); final boolean mark = col != null; r.pos = view.gui.context.marked.ftpos != null ? view.gui.context.marked.ftpos.get(data, pre) : null; g.setColor(mark ? col : GUIConstants.color(lvl)); if (r.w < l.x + l.w || r.h < l.y + l.h || off < 2 || ViewData.leaf(gopts, data, pre)) { g.fillRect(r.x, r.y, r.w, r.h); } else { // painting only border for non-leaf nodes.. g.fillRect(r.x, r.y, l.x, r.h); g.fillRect(r.x, r.y, r.w, l.y); g.fillRect(r.x + r.w - l.w, r.y, l.w, r.h); g.fillRect(r.x, r.y + r.h - l.h, r.w, l.h); } if (!full) { col = mark ? GUIConstants.colormark3 : GUIConstants.color(lvl + 2); g.setColor(col); g.drawRect(r.x, r.y, r.w, r.h); col = mark ? GUIConstants.colormark4 : GUIConstants.color(Math.max(0, lvl - 2)); g.setColor(col); g.drawLine(r.x + r.w, r.y, r.x + r.w, r.y + r.h); g.drawLine(r.x, r.y + r.h, r.x + r.w, r.y + r.h); } // skip drawing of string if there is no space if (r.w <= 3 || r.h < GUIConstants.fontSize) continue; r.x += 3; r.w -= 3; final int kind = data.kind(pre); if (kind == Data.ELEM || kind == Data.DOC) { g.setColor(Color.black); g.setFont(GUIConstants.font); BaseXLayout.chopString(g, ViewData.name(gopts, data, pre), r.x, r.y, r.w, fsz); } else { g.setColor(GUIConstants.color(r.level * 2 + 8)); g.setFont(GUIConstants.mfont); final byte[] text = ViewData.content(data, pre, false); r.thumb = MapRenderer.calcHeight(g, r, text, fsz) >= r.h; if (r.thumb) { MapRenderer.drawThumbnails(g, r, text, fsz); } else { MapRenderer.drawText(g, r, text, fsz); } } r.x -= 3; r.w += 3; } }