/** Handles the alternative partial disc selection triggered by pressing a key. */ public void handleKeyboardAlternativeDiscSelection() { Set<Integer> setSelection = selectionManager.getElements(SelectionType.SELECTION); PartialDisc pdCurrentMouseOverElement = null; int iDisplayedHierarchyDepth = Math.min(iMaxDisplayedHierarchyDepth, pdCurrentRootElement.getDepth()); if ((setSelection != null)) { for (Integer elementID : setSelection) { pdCurrentMouseOverElement = hashPartialDiscs.get(elementID); if (pdCurrentMouseOverElement.isCurrentlyDisplayed( pdCurrentRootElement, iDisplayedHierarchyDepth)) { drawingController.handleAlternativeSelection(pdCurrentMouseOverElement); return; } } } Set<Integer> setMouseOver = selectionManager.getElements(SelectionType.MOUSE_OVER); if ((setMouseOver != null)) { for (Integer elementID : setMouseOver) { pdCurrentMouseOverElement = hashPartialDiscs.get(elementID); if (pdCurrentMouseOverElement.isCurrentlyDisplayed( pdCurrentRootElement, iDisplayedHierarchyDepth)) { drawingController.handleAlternativeSelection(pdCurrentMouseOverElement); return; } } } }
@Override public ASerializedView getSerializableRepresentation() { SerializedRadialHierarchyView serializedForm = new SerializedRadialHierarchyView(this); serializedForm.setMaxDisplayedHierarchyDepth(iMaxDisplayedHierarchyDepth); serializedForm.setNewSelection(bIsNewSelection); serializedForm.setDefaultDrawingStrategyType( drawingStrategyManager.getDefaultDrawingStrategy().getDrawingStrategyType()); ADrawingState currentDrawingState = drawingController.getCurrentDrawingState(); if (pdCurrentRootElement != null) { if ((currentDrawingState.getType() == EDrawingStateType.DRAWING_STATE_DETAIL_OUTSIDE) || (currentDrawingState.getType() == EDrawingStateType.DRAWING_STATE_FULL_HIERARCHY)) { serializedForm.setDrawingStateType(currentDrawingState.getType()); serializedForm.setRootElementID(pdCurrentRootElement.getElementID()); serializedForm.setSelectedElementID(pdCurrentSelectedElement.getElementID()); serializedForm.setRootElementStartAngle(pdCurrentRootElement.getCurrentStartAngle()); serializedForm.setSelectedElementStartAngle( pdCurrentSelectedElement.getCurrentStartAngle()); } else { HistoryEntry historyEntry = navigationHistory.getCurrentHistoryEntry(); serializedForm.setDrawingStateType(historyEntry.getDrawingState().getType()); serializedForm.setRootElementID(historyEntry.getRootElement().getElementID()); serializedForm.setSelectedElementID(historyEntry.getSelectedElement().getElementID()); serializedForm.setRootElementStartAngle(historyEntry.getRootElementStartAngle()); serializedForm.setSelectedElementStartAngle(historyEntry.getSelectedElementStartAngle()); } } return serializedForm; }
/** * Sets up the current display of the RadialHierarchy view according to the specified parameters. * * @param drawingStateType DrawingState that shall be used. * @param drawingStrategyType Default drawing strategy that shall be used. * @param isNewSelection Determines if the selected element has been newly selected. * @param rootElementID ID of current root element. * @param selectedElementID ID of selected element. * @param rootElementStartAngle Start angle of the root element. * @param selectedElementStartAngle Start angle of the selected element. * @param maxDisplayedHierarchyDepth Maximum hierarchy depth that shall be displayed. */ public void setupDisplay( EDrawingStateType drawingStateType, EPDDrawingStrategyType drawingStrategyType, boolean isNewSelection, int rootElementID, int selectedElementID, float rootElementStartAngle, float selectedElementStartAngle, int maxDisplayedHierarchyDepth) { this.iMaxDisplayedHierarchyDepth = maxDisplayedHierarchyDepth; bIsNewSelection = isNewSelection; PartialDisc pdTemp = hashPartialDiscs.get(rootElementID); drawingController.setDrawingState(drawingStateType); drawingStrategyManager.setDefaultStrategy(drawingStrategyType); if (pdTemp != null) { setCurrentRootElement(pdTemp); pdCurrentSelectedElement = hashPartialDiscs.get(selectedElementID); pdCurrentRootElement.setCurrentStartAngle(rootElementStartAngle); if (pdCurrentSelectedElement != null) { pdCurrentSelectedElement.setCurrentStartAngle(selectedElementStartAngle); } } setDisplayListDirty(); }
@Override public void handleSelection(PartialDisc pdSelected) { PartialDisc pdRealRootElement = radialHierarchy.getRealRootElement(); PartialDisc pdCurrentRootElement = radialHierarchy.getCurrentRootElement(); if (pdSelected != pdRealRootElement && pdSelected.hasChildren()) { pdCurrentRootElement.setPDDrawingStrategyChildren( radialHierarchy.getDrawingStrategyManager().getDefaultDrawingStrategy(), iDisplayedHierarchyDepth); if (pdSelected == pdCurrentRootElement) { radialHierarchy.setCurrentSelectedElement(pdSelected); drawingController.setDrawingState(EDrawingStateType.ANIMATION_PARENT_ROOT_ELEMENT); } else { radialHierarchy.setCurrentSelectedElement(pdSelected); drawingController.setDrawingState(EDrawingStateType.ANIMATION_NEW_ROOT_ELEMENT); } radialHierarchy.setDisplayListDirty(); } else { radialHierarchy.setNewSelection(SelectionType.SELECTION, pdSelected); radialHierarchy.setDisplayListDirty(); } }
/** * Initializes a new hierarchy of partial discs according to a tree of cluster nodes and other * parameters. * * @param <E> Concrete Type of IHierarchyData * @param tree Tree of hierarchy data objects which is used to build the partial disc tree. * @param idType IDType of the hierarchy data objects. * @param dataEventManager Concrete DataEventManager that is responsible for handling and * triggering data specific events. * @param alColorModes List of drawing strategies that shall be used as color modes. */ public <E extends AHierarchyElement<E>> void initHierarchy( Tree<E> tree, E heRoot, ADataEventManager dataEventManager, ArrayList<EPDDrawingStrategyType> alColorModes) { hashPartialDiscs.clear(); selectionManager = new SelectionManager(tree.getNodeIDType()); partialDiscTree = new Tree<PartialDisc>(); navigationHistory.reset(); drawingController.setDrawingState(EDrawingStateType.DRAWING_STATE_FULL_HIERARCHY); LabelManager.get().clearLabels(); drawingStrategyManager.init(pickingManager, uniqueID, alColorModes); PartialDisc pdRoot = new PartialDisc( partialDiscTree, heRoot, drawingStrategyManager.getDefaultDrawingStrategy()); partialDiscTree.setRootNode(pdRoot); partialDiscTree.setLeafIDType(tree.getLeaveIDType()); partialDiscTree.setNodeIDType(tree.getNodeIDType()); hashPartialDiscs.put(heRoot.getID(), pdRoot); // selectionManager.initialAdd(heRoot.getID()); buildTree(tree, heRoot, pdRoot); pdRoot.calculateLargestChildren(); iMaxDisplayedHierarchyDepth = DISP_HIER_DEPTH_DEFAULT; this.dataEventManager = dataEventManager; this.dataEventManager.registerEventListeners(); pdCurrentRootElement = pdRoot; pdCurrentSelectedElement = pdRoot; pdRealRootElement = pdRoot; navigationHistory.addNewHistoryEntry( drawingController.getCurrentDrawingState(), pdCurrentRootElement, pdCurrentSelectedElement, iMaxDisplayedHierarchyDepth); selectionManager.addToType(SelectionType.SELECTION, pdCurrentRootElement.getElementID()); controlBox = new Rectangle(0, 0, 0.3f, 0.2f); upwardNavigationSlider = new OneWaySlider( new Vec2f(controlBox.getMinX() + 0.1f, controlBox.getMinY() + 0.1f), 0.2f, 1f, pdRealRootElement.getHierarchyLevel(), 1, 0, pdRealRootElement.getDepth() - 1); upwardNavigationSlider.setMinSize(80); }
@Override public void draw(float fXCenter, float fYCenter, GL2 gl, GLU glu) { HashMap<PartialDisc, PDDrawingStrategySelected> mapSelectedDrawingStrategies = new HashMap<PartialDisc, PDDrawingStrategySelected>(); parentIndicatorType = SelectionType.NORMAL; initDrawingStrategies(mapSelectedDrawingStrategies); PartialDisc pdCurrentRootElement = radialHierarchy.getCurrentRootElement(); gl.glLoadIdentity(); gl.glTranslatef(fXCenter, fYCenter, 0); float fHierarchyOuterRadius = Math.min( fXCenter * RadialHierarchyRenderStyle.USED_SCREEN_PERCENTAGE, fYCenter * RadialHierarchyRenderStyle.USED_SCREEN_PERCENTAGE); float fDiscWidth = fHierarchyOuterRadius / iDisplayedHierarchyDepth; pdCurrentRootElement.drawHierarchyFull(gl, glu, fDiscWidth, iDisplayedHierarchyDepth); // The selected elements have to be drawn (again using their own drawing // strategy) at last for // correct antialiasing for (PartialDisc pdSelected : mapSelectedDrawingStrategies.keySet()) { PDDrawingStrategySelected dsCurrent = mapSelectedDrawingStrategies.get(pdSelected); dsCurrent.drawPartialDisc(gl, glu, pdSelected); } if (parentIndicatorType != SelectionType.NORMAL) { gl.glPushClientAttrib(GL.GL_COLOR_BUFFER_BIT); if (parentIndicatorType == SelectionType.SELECTION) gl.glColor3fv(SelectionType.SELECTION.getColor().getRGB(), 0); else gl.glColor3fv(SelectionType.MOUSE_OVER.getColor().getRGB(), 0); GLPrimitives.renderCircle(glu, fDiscWidth / 2.0f, 100); GLPrimitives.renderCircleBorder(gl, glu, fDiscWidth / 2.0f, 100, 2); gl.glPopAttrib(); } LabelManager.get() .drawAllLabels(gl, glu, fXCenter * 2.0f, fYCenter * 2.0f, fHierarchyOuterRadius); LabelManager.get().clearLabels(); radialHierarchy.setNewSelection(false); }
@Override public void handleAlternativeSelection(PartialDisc pdSelected) { PartialDisc pdCurrentRootElement = radialHierarchy.getCurrentRootElement(); if (pdSelected != pdCurrentRootElement && pdSelected.hasChildren() && pdSelected.getCurrentDepth() > 1) { pdCurrentRootElement.setPDDrawingStrategyChildren( radialHierarchy.getDrawingStrategyManager().getDefaultDrawingStrategy(), iDisplayedHierarchyDepth); radialHierarchy.setCurrentSelectedElement(pdSelected); drawingController.setDrawingState(EDrawingStateType.ANIMATION_POP_OUT_DETAIL_OUTSIDE); radialHierarchy.setDisplayListDirty(); } }
/** * A new selection will be set in the selection manager with the specified parameters. A * ClusterNodeSelectionEvent with the new selection will be triggered. If the selected element * corresponds to a gene, a SelectionUpdateEvent will also be triggered. * * @param selectionType Type of selection. * @param pdSelected Element that has been selected. */ public void setNewSelection(SelectionType selectionType, PartialDisc pdSelected) { selectionManager.clearSelections(); selectionManager.addToType(selectionType, pdSelected.getElementID()); dataEventManager.triggerDataSelectionEvents(selectionType, pdSelected); if (selectionType == SelectionType.SELECTION) { bIsNewSelection = true; } else { bIsNewSelection = false; } }
/** * Updates the current root element according to the position of the upward navigation silder, * i.e. a parent of the current root element with the hierarchy level of the slider position will * be the new root element. */ private void updateHierarchyAccordingToNavigationSlider() { PartialDisc pdNewRootElement = pdCurrentRootElement.getParentWithLevel(upwardNavigationSlider.getSelectedValue()); if (pdNewRootElement != null) { pdCurrentRootElement = pdNewRootElement; bIsNewSelection = true; PartialDisc pdSelectedElement = drawingController.getCurrentDrawingState().getSelectedElement(); if (pdSelectedElement != null) { pdCurrentSelectedElement = pdSelectedElement; pdSelectedElement.setCurrentStartAngle(0); } navigationHistory.addNewHistoryEntry( drawingController.getCurrentDrawingState(), pdCurrentRootElement, pdCurrentSelectedElement, iMaxDisplayedHierarchyDepth); setDisplayListDirty(); setNewSelection(SelectionType.SELECTION, pdCurrentSelectedElement); } }
/** * Sets an element that will be displayed as root element. * * @param pdCurrentRootElement New element that will be displayed as root element. */ public void setCurrentRootElement(PartialDisc pdCurrentRootElement) { this.pdCurrentRootElement = pdCurrentRootElement; upwardNavigationSlider.setSelectedValue(pdCurrentRootElement.getHierarchyLevel()); }
@Override protected void handlePickingEvents( PickingType pickingType, PickingMode pickingMode, int externalID, Pick pick) { if (detailLevel == EDetailLevel.VERY_LOW) { return; } switch (pickingType) { case RAD_HIERARCHY_PDISC_SELECTION: PartialDisc pdPickedElement = hashPartialDiscs.get(externalID); switch (pickingMode) { case CLICKED: if (pdPickedElement != null) drawingController.handleSelection(pdPickedElement); break; case MOUSE_OVER: if (pdPickedElement != null) drawingController.handleMouseOver(pdPickedElement); break; case RIGHT_CLICKED: if (pdPickedElement != null) { // Prevent handling of non genetic data in context // menu if (!dataDomain.getDataDomainID().equals("org.caleydo.datadomain.genetic")) break; if (!pdPickedElement.hasChildren()) { AContextMenuItem menuItem = new BookmarkMenuItem( "Bookmark " + dataDomain.getRecordLabel(dataDomain.getRecordIDType(), externalID), dataDomain.getRecordIDType(), externalID); getContextMenuCreator().addContextMenuItem(menuItem); } else { AContextMenuItem menuItem = new DetailOutsideItem(externalID); getContextMenuCreator().addContextMenuItem(menuItem); } break; } drawingController.handleAlternativeSelection(pdPickedElement); break; default: return; } break; case RAD_HIERARCHY_SLIDER_SELECTION: switch (pickingMode) { case CLICKED: if (externalID == iUpwardNavigationSliderID) { if (upwardNavigationSlider.handleSliderSelection(pickingType)) { updateHierarchyAccordingToNavigationSlider(); setDisplayListDirty(); } } break; default: return; } break; case RAD_HIERARCHY_SLIDER_BUTTON_SELECTION: switch (pickingMode) { case CLICKED: if (externalID == iUpwardNavigationSliderButtonID) { if (upwardNavigationSlider.handleSliderSelection(pickingType)) { updateHierarchyAccordingToNavigationSlider(); setDisplayListDirty(); } } break; default: return; } break; case RAD_HIERARCHY_SLIDER_BODY_SELECTION: switch (pickingMode) { case CLICKED: if (externalID == iUpwardNavigationSliderBodyID) { if (upwardNavigationSlider.handleSliderSelection(pickingType)) { updateHierarchyAccordingToNavigationSlider(); setDisplayListDirty(); } } break; default: return; } break; default: break; } }
/** * Initializes drawing strategies for all selected elements of the radial hierarchy's selection * manager. * * @param mapSelectedDrawingStrategies Map is filled with key-value pairs where the key is a * selected partial disc and its value is the corresponding drawing strategy. */ private void initDrawingStrategies( HashMap<PartialDisc, PDDrawingStrategySelected> mapSelectedDrawingStrategies) { PartialDisc pdCurrentRootElement = radialHierarchy.getCurrentRootElement(); int iMaxDisplayedHierarchyDepth = radialHierarchy.getMaxDisplayedHierarchyDepth(); pdCurrentMouseOverElement = null; iDisplayedHierarchyDepth = Math.min(iMaxDisplayedHierarchyDepth, pdCurrentRootElement.getDepth()); DrawingStrategyManager drawingStrategyManager = radialHierarchy.getDrawingStrategyManager(); APDDrawingStrategy dsDefault = drawingStrategyManager.getDefaultDrawingStrategy(); SelectionManager selectionManager = radialHierarchy.getSelectionManager(); Set<Integer> setSelection = selectionManager.getElements(SelectionType.SELECTION); Set<Integer> setMouseOver = selectionManager.getElements(SelectionType.MOUSE_OVER); pdCurrentRootElement.setPDDrawingStrategyChildren(dsDefault, iDisplayedHierarchyDepth); HashMap<PartialDisc, SelectionType> mapSelectedElements = new HashMap<PartialDisc, SelectionType>(); HashMap<PartialDisc, SelectionType> mapChildIndictatorElements = new HashMap<PartialDisc, SelectionType>(); boolean bIsNewSelection = radialHierarchy.isNewSelection(); // Take the mouse over element from the selected elements, if any and if // displayed. for (Integer elementID : setSelection) { PartialDisc pdSelected = radialHierarchy.getPartialDisc(elementID); if (pdSelected != null) { if (pdSelected.isCurrentlyDisplayed(pdCurrentRootElement, iDisplayedHierarchyDepth)) { pdCurrentMouseOverElement = pdSelected; break; } } } for (Integer elementID : setSelection) { PartialDisc pdSelected = radialHierarchy.getPartialDisc(elementID); if (pdSelected != null) { if (pdCurrentMouseOverElement == null && bIsNewSelection) { PartialDisc pdParent = pdSelected.getParent(); if (pdParent == null) { pdCurrentRootElement = pdSelected; } else { pdCurrentRootElement = pdParent; } iDisplayedHierarchyDepth = Math.min(iMaxDisplayedHierarchyDepth, pdCurrentRootElement.getDepth()); radialHierarchy.setCurrentRootElement(pdCurrentRootElement); radialHierarchy.setCurrentSelectedElement(pdCurrentRootElement); navigationHistory.addNewHistoryEntry( this, pdCurrentRootElement, pdCurrentRootElement, iMaxDisplayedHierarchyDepth); mapSelectedElements.put(pdSelected, SelectionType.SELECTION); pdCurrentMouseOverElement = pdSelected; continue; } PartialDisc pdIndicated = pdSelected.getFirstVisibleElementOnParentPathToRoot( pdCurrentRootElement, iDisplayedHierarchyDepth); if (pdIndicated == pdSelected) { mapSelectedElements.put(pdSelected, SelectionType.SELECTION); } else if (pdIndicated == null) { parentIndicatorType = SelectionType.SELECTION; } else { mapChildIndictatorElements.put(pdIndicated, SelectionType.SELECTION); } } } for (Integer elementID : setMouseOver) { PartialDisc pdMouseOver = radialHierarchy.getPartialDisc(elementID); if (pdMouseOver != null) { if (pdCurrentMouseOverElement == null) { if (pdMouseOver.isCurrentlyDisplayed(pdCurrentRootElement, iDisplayedHierarchyDepth)) { mapSelectedElements.put(pdMouseOver, SelectionType.MOUSE_OVER); pdCurrentMouseOverElement = pdMouseOver; continue; } } PartialDisc pdIndicated = pdMouseOver.getFirstVisibleElementOnParentPathToRoot( pdCurrentRootElement, iDisplayedHierarchyDepth); if (pdIndicated == pdMouseOver) { if (!mapSelectedElements.containsKey(pdMouseOver)) mapSelectedElements.put(pdMouseOver, SelectionType.MOUSE_OVER); } else if (pdIndicated == null) { if (parentIndicatorType != SelectionType.SELECTION) parentIndicatorType = SelectionType.MOUSE_OVER; } else { if (!mapChildIndictatorElements.containsKey(pdIndicated)) mapChildIndictatorElements.put(pdIndicated, SelectionType.MOUSE_OVER); } } } for (PartialDisc pdSelected : mapSelectedElements.keySet()) { PDDrawingStrategySelected dsCurrent = (PDDrawingStrategySelected) drawingStrategyManager.createDrawingStrategy(EPDDrawingStrategyType.SELECTED); if (mapSelectedElements.get(pdSelected) == SelectionType.SELECTION) { dsCurrent.setBorderColor(SelectionType.SELECTION.getColor().getRGBA()); } if (mapChildIndictatorElements.containsKey(pdSelected)) { if (mapChildIndictatorElements.get(pdSelected) == SelectionType.SELECTION) { dsCurrent.setChildIndicatorColor(SelectionType.SELECTION.getColor().getRGBA()); } else { dsCurrent.setChildIndicatorColor(SelectionType.MOUSE_OVER.getColor().getRGBA()); } mapChildIndictatorElements.remove(pdSelected); } mapSelectedDrawingStrategies.put(pdSelected, dsCurrent); pdSelected.setPDDrawingStrategy(dsCurrent); } for (PartialDisc pdIndicated : mapChildIndictatorElements.keySet()) { APDDrawingStrategyChildIndicator dsCurrent = (APDDrawingStrategyChildIndicator) drawingStrategyManager.createDrawingStrategy( drawingStrategyManager.getDefaultDrawingStrategy().getDrawingStrategyType()); if (mapChildIndictatorElements.get(pdIndicated) == SelectionType.SELECTION) { dsCurrent.setChildIndicatorColor(SelectionType.SELECTION.getColor().getRGBA()); } else { dsCurrent.setChildIndicatorColor(SelectionType.MOUSE_OVER.getColor().getRGBA()); } pdIndicated.setPDDrawingStrategy(dsCurrent); } if (pdCurrentMouseOverElement != null) { APDDrawingStrategyDecorator dsLabelDecorator = new PDDrawingStrategyLabelDecorator( radialHierarchy.getDataDomain().getTable().getColorMapper()); pdCurrentMouseOverElement.decoratePDDrawingStrategyChildren( dsLabelDecorator, Math.min(RadialHierarchyRenderStyle.MAX_LABELING_DEPTH, iDisplayedHierarchyDepth)); } }