public DocumentGrid( final DocumentGridTable t, String xAxisInitName, String yAxisInitName, String colorInitName) { super(new Visualization()); display = this; this.t = t; this.controller = MainController.getMainController(); // add data to visualization (tables, ...) VisualTable vt = m_vis.addTable(DATA_GROUP, t); colorAttrName = colorInitName; // init actionlist: performs initial positioning of the glyphs, axes ActionList init = new ActionList(); // add document layout action // rather than taking only the values which are present, let's pull the valid values directly // from the ML module, since some applicable values might not be present within the current // documents, but we will need these regions to be present in the visualization for dragging? // List<String> xAxisInitCategories = t.getValueListForAttribute(xAxisInitName); List<String> xAxisInitCategories = controller.getValuesForAttribute(xAxisInitName); // List<String> yAxisInitCategories = t.getValueListForAttribute(yAxisInitName); List<String> yAxisInitCategories = controller.getValuesForAttribute(yAxisInitName); documentGridLayout = new DocumentGridLayoutNested( DATA_GROUP, xAxisInitName, yAxisInitName, xAxisInitCategories, yAxisInitCategories); init.add(documentGridLayout); // add axes layout action docGridAxisLayout = new DocumentGridAxisLayout(ALL_LABEL, documentGridLayout); documentGridLayout.setAxisLayout(docGridAxisLayout); // init.add(docGridAxisLayout); // because of race conditions (DGAL requiring info from // DGL which it doesn't have until its layout proceedure has finished), DGAL is now called // directly by DGL, no longer as a separate member of the actionlist // add init actionlist to vis m_vis.putAction("init", init); // set up renderer for nodes, set rendererFactory nodeRenderer = new DocGlyphRenderer(); // perform additional optional renderer setup here // add primary renderer to visualization DefaultRendererFactory rf = new DefaultRendererFactory(); rf.setDefaultRenderer(nodeRenderer); // add auxiliary renderer for axes rf.add(new InGroupPredicate(ALL_LABEL), new DocumentGridAxisRenderer(documentGridLayout)); m_vis.setRendererFactory(rf); // ActionList for simple repaint (for simple controls) ActionList repaint = new ActionList(); repaint.add(new RepaintAction()); m_vis.putAction("repaint", repaint); // update actionlist: performs coloration, sizing ActionList updateOnce = new ActionList(); // size action // note: sizing is now controlled by the layout action // SizeAction sizeActionUpdate = new DocGlyphSizeAction(DATA_GROUP); // updateOnce.add(sizeActionUpdate); // shape action // note: now using a constant square shape ShapeAction squareShapeAction = new SquareShapeAction(); updateOnce.add(squareShapeAction); // color action(s) List<String> colorInitCategories = t.getValueListForAttribute(colorInitName); docColorAction = new DocumentColorAction(DATA_GROUP, colorInitName, colorInitCategories); updateOnce.add(docColorAction); docBorderColorAction = new DocumentBorderColorAction(DATA_GROUP); updateOnce.add(docBorderColorAction); // visibility filter docGlyphVisiblePredicate = new InGroupPredicate(DATA_GROUP); docGlyphVisibleFilter = new GlyphVisibilityFilter(DATA_GROUP, docGlyphVisiblePredicate); updateOnce.add(docGlyphVisibleFilter); // repaint action updateOnce.add(new RepaintAction()); // add update actionlist to vis m_vis.putAction("updateOnce", updateOnce); // TODO : enable proper animation // ActionList animate = new ActionList(1250); // animate.setPacingFunction(new SlowInSlowOutPacer()); // animate.add(new LocationAnimator(DATA_GROUP)); // animate.add(new SizeAction(DATA_GROUP)); // animate.add(new RepaintAction()); // m_vis.putAction("animate", animate); // get reference to glasspane glassPane = controller.getGlassPane(); // set initial / basic properties of the display setSize(700, 600); setBackground(Color.LIGHT_GRAY); setBorder(BorderFactory.createEmptyBorder(30, 20, 5, 20)); // for doc highlighting on search (partially adapted from TreeMap.java in Prefuse demo gallery) searchQ = new SearchQueryBinding(t, DocumentGridTable.NODE_TEXT); m_vis.addFocusGroup(Visualization.SEARCH_ITEMS, searchQ.getSearchSet()); searchQ .getPredicate() .addExpressionListener( new UpdateListener() { @Override public void update(Object src) { // // debug // System.out.println("\n\ndebug: "+this.getClass().getName()+": in // SEARCH_ITEMS group: "); // update focus text for all items in visualtable, wrt. query // TODO : improve efficiency of this predicate updating method String queryStr = searchQ.getSearchSet().getQuery(); Scanner querySplitter = new Scanner(queryStr); List<String> terms = new ArrayList<>(); while (querySplitter.hasNext()) { String term = querySplitter.next(); terms.add(term.trim()); } // debug // System.out.println("debug: "+this.getClass().getName()+": query // string: "+queryStr); int numRows = t.getRowCount(); for (int i = 0; i < numRows; i++) { t.setString(i, DocumentGridTable.NODE_FOCUS_TEXT, ""); String text = t.getString(i, DocumentGridTable.NODE_TEXT).toLowerCase(); boolean containsAllTerms = true; for (String term : terms) { if (!text.contains(term)) { containsAllTerms = false; break; } } // if (!containsAllTerms) { // TODO properly remove non-matching items from search set? // searchQ.getSearchSet().removeTuple(t.getTuple(i)); // // throws UnsupportedOperationException // } else { // set highlight text // do very coarse "sentence-splitting" // TODO : proper sentence parsing List<String> focusSents = new ArrayList<>(); Scanner sentSplitter = new Scanner(text); // sentSplitter.useDelimiter("[\\.\n]"); // split on // period or newline sentSplitter.useDelimiter("[\\.]"); // split on period only while (sentSplitter.hasNext()) { String sent = sentSplitter.next(); for (String term : terms) { if (sent.contains(term)) { focusSents.add(sent); } } } if (focusSents.size() > 0) { StringBuilder focusText = new StringBuilder(); focusText.append(FOCUS_SENT_SPLITTER); for (String focusSent : focusSents) { focusText.append(focusSent); focusText.append(FOCUS_SENT_SPLITTER + "\n"); } t.setString(i, DocumentGridTable.NODE_FOCUS_TEXT, focusText.toString()); } // } } // run repaint actions m_vis.run("updateOnce"); } }); // set up control listeners // zoom with wheel // addControlListener(new WheelZoomControl()); // zoom with background right-drag // addControlListener(new ZoomControl(Control.RIGHT_MOUSE_BUTTON)); // pan with background left-drag // addControlListener(new PanControl(Control.RIGHT_MOUSE_BUTTON)); // drag control for moving items to new cells docDragControl = new DocGridDragControl(DATA_GROUP, documentGridLayout, controller); addControlListener(docDragControl); // control for loading document details in glasspane docSelectControl = new DocumentSelectControl(glassPane); addControlListener(docSelectControl); // run actionlists m_vis.alwaysRunAfter("init", "updateOnce"); m_vis.run("init"); }