public void updateYAxis(String yAxisAttrName) { // pull applicable values from ML module List<String> yAxisCategories = MainController.getMainController().getValuesForAttribute(yAxisAttrName); documentGridLayout.updateYAxis(yAxisAttrName, yAxisCategories); // update the visual axis indicator as well docGridAxisLayout.docGridLayoutUpdated(); // m_vis.run("repaint"); // (don't yet run update actions, since the Controller may be // modifying multiple axes; let controller call updateView() itself once it's done updating the // attributes of the view) }
@Override public void itemReleased(VisualItem item, MouseEvent e) { // when right-mouse released, release the dragged document glyph if (!SwingUtilities.isRightMouseButton(e)) { return; } // debug System.out.println("debug: " + this.getClass().getName() + ": item released"); if (dragged) { activeItem = null; item.setFixed(wasFixed); dragged = false; } // clear the focus Visualization vis = item.getVisualization(); vis.getFocusGroup(Visualization.FOCUS_ITEMS).clear(); // determine whether item is in same region or new region; // if new region, call controller to update attr vals double x = item.getX(); double y = item.getY(); double w = item.getDouble(WIDTH); double h = item.getDouble(HEIGHT); int newRegionX = -1; int newRegionY = -1; String xAttrName = docGridLayout.getXAttr(); String yAttrName = docGridLayout.getYAttr(); List<String> xCats = docGridLayout.getXCats(); List<String> yCats = docGridLayout.getYCats(); List<Integer> xCatRegionSizes = docGridLayout.getXCatRegionSizes(); List<Integer> yCatRegionSizes = docGridLayout.getYCatRegionSizes(); List<Integer> xCatPositions = docGridLayout.getXCatPositions(); List<Integer> yCatPositions = docGridLayout.getYCatPositions(); // for each region, get start and range; for (int i = 0; i < xCats.size(); i++) { int xRegionStart = xCatPositions.get(i); int xRegionEnd = xRegionStart + xCatRegionSizes.get(i); if (xRegionStart < x + (w / 2.) && x + (w / 2.) < xRegionEnd) { newRegionX = i; } } for (int i = 0; i < yCats.size(); i++) { int yRegionStart = yCatPositions.get(i); int yRegionEnd = yRegionStart + yCatRegionSizes.get(i); if (yRegionStart < y + (h / 2.) && y + (h / 2.) < yRegionEnd) { newRegionY = i; } } int docID = item.getInt(DocumentGridTable.NODE_ID); // debug // System.out.println("debug: item moved: // docID="+docID+"xOrig="+xCats.get(origRegionX)+", xNew="+xCats.get(newRegionX)+", // yOrig="+yCats.get(origRegionY)+", yNew="+yCats.get(newRegionY)); // update for x and y separately // if (origRegionX != newRegionX && newRegionX != -1) { String newCatX = xCats.get(newRegionX); controller.updateDocumentAttr(docID, xAttrName, newCatX); controller.documentAttributesUpdated(docID); // } // if (origRegionY != newRegionY && newRegionY != -1) { String newCatY = yCats.get(newRegionY); controller.updateDocumentAttr(docID, yAttrName, newCatY); controller.documentAttributesUpdated(docID); // } }
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"); }