/** * Creates and adds a single control at the given position * * @param offset * @param length * @return pair of style ranges that covers this embedded editor */ public StyleRange[] createAndAddControl(int offset, int length) { StyleRange[] styles = null; Position pos = new Position(offset, length); if (!editorPositionMap.containsValue(pos)) { ContainedEditorManager newContainedEditor = addControl(offset, length); newContainedEditor.addListener(this); styles = createStyleRange(newContainedEditor, pos); newContainedEditor.registerActions(containingEditor); editorPositionMap.put(newContainedEditor, pos); ppManager.managePosition(pos); // add the annotation in the gutter EmbeddedAnnotation annotation = new EmbeddedAnnotation(newContainedEditor); if (newContainedEditor.editorKind() == CALExpressionEditorManager.EDITOR_KIND) { annotation.setType("org.openquark.cal.eclipse.embedded.expressionAnnotation"); } else { annotation.setType("org.openquark.cal.eclipse.embedded.moduleAnnotation"); } annotation.setText(newContainedEditor.getCalContents()); // must create a new position otherwise the document object is tracking the same position // in two partitions annotationModel.addAnnotation(annotation, new Position(offset, length)); // annotationModel.collapse(annotation); editorAnnotationMap.put(newContainedEditor, annotation); } else { for (final ContainedEditorManager c : editorPositionMap.keySet()) { if (editorPositionMap.get(c).equals(pos)) { styles = createStyleRange(c, pos); break; } } } return styles; }
public void editorDeleted(ContainedEditorManager editor, ContainedEditorProperties props) { IEditorStatusLine statusLine = (IEditorStatusLine) containingEditor.getAdapter(IEditorStatusLine.class); statusLine.setMessage(false, "Editor Deleted", null); Position p = removeControl(editor, true); if (p != null) { try { containingEditor.getSelectionProvider().setSelection(new TextSelection(doc, p.offset, 0)); doc.replace(p.offset, p.length, ""); } catch (BadLocationException e) { // it's OK to ignore this // shouldn't happen anyway } } if (editor == moduleEditor) { // look for new module editor, or else it becomes null. replaceModuleEditor(null); for (final ContainedEditorManager contained : editorPositionMap.keySet()) { if (contained.editorKind() == CALModuleEditorManager.EDITOR_KIND) { replaceModuleEditor((CALModuleEditorManager) contained); break; } } } // remove this control's annotation EmbeddedAnnotation annotation = editorAnnotationMap.remove(editor); annotationModel.removeAnnotation(annotation); // remove listener editor.removeListener(this); }
/** * triggers a repaint of the styled text of the containing editor whenever the text has changed. * * <p>The repaint will update the positions of all of the embedded controls. * * <p>XXX this method is being called too many times. It is being called more than once after each * cursor change. I need to take a good look at this and determine exactly when and where it * should be called */ public void paint(int reason) { if (reason != TEXT_CHANGE && reason != ContainingEditor.EMBEDDED_REPAINT) { return; } List<ContainedEditorManager> toRemove = new LinkedList<ContainedEditorManager>(); for (final ContainedEditorManager c : editorPositionMap.keySet()) { Position model = editorPositionMap.get(c); if (!model.isDeleted()) { // map from the model to the actual display (takes into account folding) Position projected = modelToProjected(model); if (projected == null) { // position is hidden behind folding c.getControl().setVisible(false); } else { try { Point location = styledText.getLocationAtOffset(projected.offset); location.x += ContainingEditor.MARGIN; location.y += ContainingEditor.MARGIN; c.getControl().setVisible(true); c.getControl().setLocation(location); } catch (IllegalArgumentException e) { EmbeddedCALPlugin.logError("Error repainting", e); } } } else { toRemove.add(c); } } for (final ContainedEditorManager c : toRemove) { removeControl(c, true); } styledText.getParent().getParent().redraw(); }
// XXX This method is still influx. trying to get the // screen to scroll if the cursor moves off it public void editorChanged(ContainedEditorManager editor, ContainedEditorProperties props) { containingEditor.setDirty(); // ensure that if the cursor moves off the screen, then the control is // scrolled back into view if (editor == getCurrentlyActiveEditor()) { revealSelection(editor, editor.getSelection().offset); } // update the gutter annotation editorAnnotationMap.get(editor).setText(editor.getCalContents()); }
/** * Scrolls the containing editor to the given offset of the contained editor * * @param editor * @param scrollTo text offset in the embedded editor that should be revealed */ public void revealSelection(ContainedEditorManager editor, int scrollTo) { StyledText containedStyledText = (StyledText) editor.getAdapter(StyledText.class); // this progression determines the location of the offset in the coordinate system // of the containing styledText Point containedLoc = containedStyledText.getLocationAtOffset(scrollTo); Point displayLoc = containedStyledText.toDisplay(containedLoc); Point containingLoc = styledText.toControl(displayLoc); // next, we determine if this location is in the visible area. Point containingSize = styledText.getSize(); Rectangle containingBounds = new Rectangle(0, 0, containingSize.x, containingSize.y); if (!containingBounds.contains(containingLoc)) { // pad a little to the left and a little bit down containingLoc.x -= 50; containingLoc.y += 100; // if not, then perform a scroll. styledText.setTopPixel(styledText.getTopPixel() + containingLoc.y - containingSize.y); // do the same for horizontal styledText.setHorizontalPixel(styledText.getHorizontalPixel() + containingLoc.x); } paint(ContainingEditor.EMBEDDED_REPAINT); }
/** * creates the style range of the StyledText for the range of the contained editor * * <p>XXX problem will occur if there is a newline in the position. Working on this! code folding. */ private StyleRange[] createStyleRange(ContainedEditorManager c, Position p) { int offset = p.offset; int length = p.length; Rectangle rect = c.getControl().getBounds(); int ascent = rect.height - 4; int descent = 4; // use two style ranges // first style range covers the entire size of the contained editor StyleRange first = new StyleRange(); first.start = offset; first.length = Math.min(1, length); first.background = this.containingEditor.colorManager.getColor(new RGB(255, 255, 255)); first.metrics = new GlyphMetrics( ascent + ContainingEditor.MARGIN, descent + ContainingEditor.MARGIN, rect.width + 2 * ContainingEditor.MARGIN); // this style range is hidden. the height and width are 0 StyleRange second = new StyleRange(); second.start = offset + 1; second.length = length - 1; second.background = this.containingEditor.colorManager.getColor(new RGB(255, 255, 255)); second.metrics = new GlyphMetrics(0, 0, 0); second.font = TINY_FONT; return new StyleRange[] {first, second}; }
public void saveAllEditors() { String moduleName = getModuleName(); if (moduleName != null) { for (final ContainedEditorManager editor : editorPositionMap.keySet()) { // check to see if the module name is up to date if (editor.editorKind() == CALExpressionEditorManager.EDITOR_KIND) { CALExpressionEditorProperties exprProps = (CALExpressionEditorProperties) editor.getPropertiess(); if (!exprProps.getModuleName().equals(moduleName)) { // module name has changed, must re-serialize this expression editor. exprProps.setDirty(true); } } editor.doSave(); } } }
/* * Adds a control at the given position */ private ContainedEditorManager addControl(int offset, int length) { // create the control propoerties ContainedEditorProperties props; try { // get the contents by reading from the editor at the given position ASTNode editorExpression = ContainedEditorProperties.toASTNode(doc.get(offset, length)); props = EditorManagerFactory.createProperties(editorExpression); } catch (BadLocationException e) { // something about the contents was bad, create an empty editor instead EmbeddedCALPlugin.logError( "Error trying to create ContainedEditorProperties: offset: " + offset + " length: " + length, e); props = new CALExpressionEditorProperties(); } ContainedEditorManager contained = EditorManagerFactory.createManager(props); if (contained.editorKind() == CALModuleEditorManager.EDITOR_KIND) { replaceModuleEditor((CALModuleEditorManager) contained); } contained.createControl(styledText, containingEditor); contained.initializeEditorContents(containingEditor); // determine the location of the contained editor Position projected = modelToProjected(new Position(offset, 0)); Point location = styledText.getLocationAtOffset(projected.offset); location.x += ContainingEditor.MARGIN; location.y += ContainingEditor.MARGIN; contained.setLocation(location); return contained; }
/** * Removes the control from this manager. Unmanages this position, * * @param c the control to remove * @param doRemove whether or not this control should be completely removed, or just temporarily * (eg- during a save) * @return the position of the removed control */ private Position removeControl(ContainedEditorManager c, boolean doRemove) { Position p; if (doRemove) { p = editorPositionMap.remove(c); } else { p = editorPositionMap.get(c); } try { ppManager.unmanagePosition(p); if (doRemove && !p.isDeleted()) { // Position projected = modelToProjected(p); // styledText.replaceStyleRanges(projected.offset, projected.length, new // StyleRange[0]); styledText.replaceStyleRanges(p.offset, p.length, new StyleRange[0]); } } catch (NullPointerException e) { // do nothing...trying to unmanage posn after // document has already been uninstalled. } c.removeListener(this); c.dispose(); return p; }
public void editorFocusLost(ContainedEditorManager editor, ContainedEditorProperties props) { currentlyActiveEditor = null; // only change the text if there is a change from previous serialization if (props.isDirty()) { updateSerialization(editor, props); // ensure that all line heights are redrawn to their correct size containingEditor.internalGetSourceViewer().invalidateTextPresentation(); } // ensure that the actions are reset to correspond to the ContainingEditor, not the // ContainedEditor containingEditor.updateSelectionDependentActions(); containingEditor.updateStateDependentActions(); editorAnnotationMap.get(editor).setText(editor.getCalContents()); }
public void editorSaved(ContainedEditorManager editor, ContainedEditorProperties props) { updateSerialization(editor, props); editorAnnotationMap.get(editor).setText(editor.getCalContents()); }