/** Notifies all views of a data reference change. */ public void init() { final Data data = initHistory(gui.context); if (data != null) { // if a large database is opened, the user is asked if complex /// visualizations should be closed first final long size = data.meta.dbsize(); boolean open = false; for (final View v : view) open |= v.visible() && v.db(); if (open && size > LARGEDB && BaseXDialog.confirm(gui, Util.info(H_LARGE_DB, Performance.format(size)))) { for (final View v : view) if (v.visible() && v.db()) v.visible(false); } } else { // database closed: close open dialogs for (final Window w : gui.getOwnedWindows()) { if (w.isVisible() && w instanceof BaseXDialog) ((BaseXDialog) w).cancel(); } } gui.context.focused = -1; for (final View v : view) v.refreshInit(); gui.layoutViews(); gui.setTitle(data != null ? data.meta.name : null); }
/** Notifies all views of updates in the data structure. */ public void update() { final Data data = initHistory(gui.context); if (data == null) return; gui.context.marked = new Nodes(data); for (final View v : view) if (v.visible()) v.refreshUpdate(); gui.refreshControls(); }
/** * Notifies all views of a context change. * * @param nodes new context set (may be {@code null} if root nodes are addressed) * @param quick quick switch * @param vw the calling view */ public void context(final Nodes nodes, final boolean quick, final View vw) { final Context ctx = gui.context; // add new entry if current node set has not been cached yet final Nodes newn = nodes.checkRoot(); final Nodes empty = new Nodes(new int[0], ctx.data(), ctx.marked.ftpos); final Nodes curr = quick ? ctx.current() : null; final Nodes cmp = quick ? curr : ctx.marked; if (cont[hist] == null ? cmp != null : cmp == null || !cont[hist].sameAs(cmp)) { checkHist(); if (quick) { // store history entry queries[hist] = ""; marked[hist] = new Nodes(ctx.data()); // add current entry cont[++hist] = curr; } else { // store history entry final String in = gui.input.getText(); queries[hist] = in; marked[hist] = ctx.marked; // add current entry cont[++hist] = newn; queries[hist] = in; marked[hist] = empty; } histsize = hist; } ctx.set(newn, empty); for (final View v : view) if (v != vw && v.visible()) v.refreshContext(true, quick); gui.refreshControls(); }
/** * Notifies all views of a selection change. * * @param mark marked nodes * @param vw the calling view */ public void mark(final Nodes mark, final View vw) { final Context ctx = gui.context; ctx.marked = mark; for (final View v : view) if (v != vw && v.visible()) v.refreshMark(); gui.filter.setEnabled(mark.size() != 0); gui.refreshControls(); }
/** * Moves around in the internal history and notifies all views of a context change. * * @param forward move forward or backward */ public void hist(final boolean forward) { final Context ctx = gui.context; final String query; if (forward) { if (hist == histsize) return; query = queries[++hist]; } else { if (hist == 0) return; marked[hist] = ctx.marked; query = queries[--hist]; } ctx.set(cont[hist], marked[hist]); gui.input.setText(query); for (final View v : view) if (v.visible()) v.refreshContext(forward, false); gui.refreshControls(); }
@Override public void paintComponent(final Graphics g) { super.paintComponent(g); // skip if view is unavailable if (tdata.rows == null) return; gui.painting = true; g.setFont(GUIConstants.font); final int w = getWidth() - scroll.getWidth(); final int h = getHeight(); final int fsz = gui.gprop.num(GUIProp.FONTSIZE); final Context context = tdata.context; final Data data = context.data(); final int focus = gui.context.focused; final int rfocus = tdata.getRoot(data, focus); int mpos = 0; final int nCols = tdata.cols.length; final int nRows = tdata.rows.size(); final int rowH = tdata.rowH; final TableIterator ti = new TableIterator(data, tdata); final TokenBuilder[] tb = new TokenBuilder[nCols]; for (int i = 0; i < nCols; ++i) tb[i] = new TokenBuilder(); focusedString = null; final Nodes marked = context.marked; int l = scroll.pos() / rowH - 1; int posY = -scroll.pos() + l * rowH; while (++l < nRows && marked != null) { // skip when all visible rows have been painted or if data has changed if (posY > h || l >= tdata.rows.size()) break; posY += rowH; final int pre = tdata.rows.get(l); while (mpos < marked.size() && marked.list[mpos] < pre) ++mpos; // draw line g.setColor(GUIConstants.color2); g.drawLine(0, posY + rowH - 1, w, posY + rowH - 1); g.setColor(Color.white); g.drawLine(0, posY + rowH, w, posY + rowH); // verify if current node is marked or focused final boolean rm = mpos < marked.size() && marked.list[mpos] == pre; final boolean rf = pre == rfocus; final int col = rm ? rf ? 5 : 4 : 3; if (rm || rf) { g.setColor(GUIConstants.color(col)); g.fillRect(0, posY - 1, w, rowH); g.setColor(GUIConstants.color(col + 4)); g.drawLine(0, posY - 1, w, posY - 1); } g.setColor(Color.black); // skip drawing of text during animation if (rowH < fsz) continue; // find all row contents ti.init(pre); int fcol = -1; while (ti.more()) { final int c = ti.col; if (ti.pre == focus || data.parent(ti.pre, data.kind(ti.pre)) == focus) fcol = c; // add content to column (skip too long contents)... if (tb[c].size() < 100) { if (tb[c].size() != 0) tb[c].add("; "); tb[c].add(data.text(ti.pre, ti.text)); } } // add dots if content is too long for (final TokenBuilder t : tb) if (t.size() > 100) t.add(DOTS); // draw row contents byte[] focusStr = null; int fx = -1; double x = 1; for (int c = 0; c < nCols; ++c) { // draw single column final double cw = w * tdata.cols[c].width; final double ce = x + cw; if (ce != 0) { final byte[] str = tb[c].size() != 0 ? tb[c].finish() : null; if (str != null) { if (tdata.mouseX > x && tdata.mouseX < ce || fcol == c) { fx = (int) x; focusStr = str; } BaseXLayout.chopString(g, str, (int) x + 1, posY + 2, (int) cw - 4, fsz); tb[c].reset(); } } x = ce; } // highlight focused entry if (rf || fcol != -1) { if (focusStr != null) { final int sw = BaseXLayout.width(g, focusStr) + 8; if (fx > w - sw - 2) fx = w - sw - 2; g.setColor(GUIConstants.color(col + 2)); g.fillRect(fx - 2, posY, sw, rowH - 1); g.setColor(Color.black); BaseXLayout.chopString(g, focusStr, fx + 1, posY + 2, sw, fsz); // cache focused string focusedString = string(focusStr); final int i = focusedString.indexOf("; "); if (i != -1) focusedString = focusedString.substring(0, i); } } } gui.painting = false; }