Index: openide/text/src/org/openide/text/CloneableEditor.java =================================================================== RCS file: /cvs/openide/text/src/org/openide/text/CloneableEditor.java,v retrieving revision 1.5 diff -u -r1.5 CloneableEditor.java --- openide/text/src/org/openide/text/CloneableEditor.java 22 Jul 2005 06:22:14 -0000 1.5 +++ openide/text/src/org/openide/text/CloneableEditor.java 20 Sep 2005 09:14:17 -0000 @@ -11,7 +11,8 @@ * Microsystems, Inc. All Rights Reserved. */ package org.openide.text; - +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import org.openide.ErrorManager; import org.openide.awt.UndoRedo; import org.openide.cookies.EditorCookie; @@ -19,6 +20,7 @@ import org.openide.util.Mutex; import org.openide.util.NbBundle; import org.openide.util.Task; +import org.openide.util.WeakSet; import org.openide.util.actions.SystemAction; import org.openide.windows.CloneableOpenSupport; import org.openide.windows.CloneableTopComponent; @@ -29,7 +31,9 @@ import java.awt.BorderLayout; import java.awt.Component; +import java.awt.Container; import java.awt.Dimension; +import java.awt.Insets; import java.awt.Rectangle; import java.io.IOException; @@ -37,8 +41,14 @@ import java.io.ObjectInput; import java.io.ObjectOutput; import java.io.ObjectStreamException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; import javax.swing.Action; +import javax.swing.BoundedRangeModel; import javax.swing.JEditorPane; import javax.swing.JScrollPane; import javax.swing.JToolBar; @@ -50,7 +60,6 @@ import javax.swing.text.Document; import javax.swing.text.EditorKit; - /** Cloneable top component to hold the editor kit. */ public class CloneableEditor extends CloneableTopComponent implements CloneableEditorSupport.Pane { @@ -162,6 +171,10 @@ super.componentShowing(); initialize(); } + + private static final int PANE_COUNT = 2; + QuietEditorPane[] panes = new QuietEditorPane[PANE_COUNT]; + Component[] comps = new Component[PANE_COUNT]; /** Performs needed initialization */ private void initialize() { @@ -179,90 +192,203 @@ Document doc = support.getDocument(); setLayout(new BorderLayout()); + + JScrollPane[] scrolls = new JScrollPane[PANE_COUNT]; + + for (int i=0; i < PANE_COUNT; i++) { - final QuietEditorPane pane = new QuietEditorPane(); - - pane.getAccessibleContext().setAccessibleName( - NbBundle.getMessage(CloneableEditor.class, "ACS_CloneableEditor_QuietEditorPane", this.getName()) - ); - pane.getAccessibleContext().setAccessibleDescription( - NbBundle.getMessage( - CloneableEditor.class, "ACSD_CloneableEditor_QuietEditorPane", - this.getAccessibleContext().getAccessibleDescription() - ) - ); + final QuietEditorPane pane = new QuietEditorPane(); + panes[i] = pane; - this.pane = pane; - - // Init action map: cut,copy,delete,paste actions. - javax.swing.ActionMap am = getActionMap(); + pane.getAccessibleContext().setAccessibleName( + NbBundle.getMessage(CloneableEditor.class, "ACS_CloneableEditor_QuietEditorPane", this.getName()) + ); + pane.getAccessibleContext().setAccessibleDescription( + NbBundle.getMessage( + CloneableEditor.class, "ACSD_CloneableEditor_QuietEditorPane", + this.getAccessibleContext().getAccessibleDescription() + ) + ); - //#43157 - editor actions need to be accessible from outside using the TopComponent.getLookup(ActionMap.class) call. - // used in main menu enabling/disabling logic. - javax.swing.ActionMap paneMap = pane.getActionMap(); - am.setParent(paneMap); + this.pane = pane; - //#41223 set the defaults befor the custom editor + kit get initialized, giving them opportunity to - // override defaults.. - paneMap.put(DefaultEditorKit.cutAction, getAction(DefaultEditorKit.cutAction)); - paneMap.put(DefaultEditorKit.copyAction, getAction(DefaultEditorKit.copyAction)); - paneMap.put("delete", getAction(DefaultEditorKit.deleteNextCharAction)); // NOI18N - paneMap.put(DefaultEditorKit.pasteAction, getAction(DefaultEditorKit.pasteAction)); + // Init action map: cut,copy,delete,paste actions. + javax.swing.ActionMap am = getActionMap(); - pane.setEditorKit(support.cesKit()); + //#43157 - editor actions need to be accessible from outside using the TopComponent.getLookup(ActionMap.class) call. + // used in main menu enabling/disabling logic. + javax.swing.ActionMap paneMap = pane.getActionMap(); + am.setParent(paneMap); + + //#41223 set the defaults befor the custom editor + kit get initialized, giving them opportunity to + // override defaults.. + paneMap.put(DefaultEditorKit.cutAction, getAction(DefaultEditorKit.cutAction)); + paneMap.put(DefaultEditorKit.copyAction, getAction(DefaultEditorKit.copyAction)); + paneMap.put("delete", getAction(DefaultEditorKit.deleteNextCharAction)); // NOI18N + paneMap.put(DefaultEditorKit.pasteAction, getAction(DefaultEditorKit.pasteAction)); + + pane.setEditorKit(support.cesKit()); + + pane.setDocument(doc); + + if (doc instanceof NbDocument.CustomEditor) { + NbDocument.CustomEditor ce = (NbDocument.CustomEditor) doc; + customComponent = ce.createEditor(pane); + + if (customComponent == null) { + throw new IllegalStateException( + "Document:" + doc // NOI18N + +" implementing NbDocument.CustomEditor may not" // NOI18N + +" return null component" + ); // NOI18N + } - pane.setDocument(doc); + comps[i] = support.wrapEditorComponent(customComponent); + add(comps[i], i == 0 ? BorderLayout.EAST : BorderLayout.WEST); + } else { // not custom editor + + // remove default JScrollPane border, borders are provided by window system + JScrollPane noBorderPane = new JScrollPane(pane); + pane.setBorder(null); + comps[i] = support.wrapEditorComponent(noBorderPane); + add(comps[i], i == 0 ? BorderLayout.EAST : BorderLayout.WEST); + } - if (doc instanceof NbDocument.CustomEditor) { - NbDocument.CustomEditor ce = (NbDocument.CustomEditor) doc; - customComponent = ce.createEditor(pane); + if (doc instanceof NbDocument.CustomToolbar && customToolbar != null) { + NbDocument.CustomToolbar ce = (NbDocument.CustomToolbar) doc; + customToolbar = ce.createToolbar(pane); + + if (customToolbar == null) { + throw new IllegalStateException( + "Document:" + doc // NOI18N + +" implementing NbDocument.CustomToolbar may not" // NOI18N + +" return null toolbar" + ); // NOI18N + } - if (customComponent == null) { - throw new IllegalStateException( - "Document:" + doc // NOI18N - +" implementing NbDocument.CustomEditor may not" // NOI18N - +" return null component" - ); // NOI18N + Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N + customToolbar.setBorder(b); + add(customToolbar, BorderLayout.NORTH); } - add(support.wrapEditorComponent(customComponent), BorderLayout.CENTER); - } else { // not custom editor - - // remove default JScrollPane border, borders are provided by window system - JScrollPane noBorderPane = new JScrollPane(pane); - pane.setBorder(null); - add(support.wrapEditorComponent(noBorderPane), BorderLayout.CENTER); - } + pane.setWorking(QuietEditorPane.ALL); - if (doc instanceof NbDocument.CustomToolbar) { - NbDocument.CustomToolbar ce = (NbDocument.CustomToolbar) doc; - customToolbar = ce.createToolbar(pane); + // set the caret to right possition if this component was deserialized + if (cursorPosition != -1) { + Caret caret = pane.getCaret(); - if (customToolbar == null) { - throw new IllegalStateException( - "Document:" + doc // NOI18N - +" implementing NbDocument.CustomToolbar may not" // NOI18N - +" return null toolbar" - ); // NOI18N + if (caret != null) { + caret.setDot(cursorPosition); + } } - - Border b = (Border) UIManager.get("Nb.Editor.Toolbar.border"); //NOI18N - customToolbar.setBorder(b); - add(customToolbar, BorderLayout.NORTH); } - - pane.setWorking(QuietEditorPane.ALL); - - // set the caret to right possition if this component was deserialized - if (cursorPosition != -1) { - Caret caret = pane.getCaret(); - - if (caret != null) { - caret.setDot(cursorPosition); + this.pane = panes[0]; + support.ensureAnnotationsLoaded(); + } + + public void addNotify() { + super.addNotify(); + if (!attached) { + SwingUtilities.invokeLater(new R()); + } + } + + private class R implements Runnable { + public void run() { + JScrollPane[] p = new JScrollPane[panes.length]; + for (int i=0; i < panes.length; i++) { + if (panes[i] != null) { + JScrollPane pane = (JScrollPane) + SwingUtilities.getAncestorOfClass(JScrollPane.class, panes[i]); + p[i] = pane; + if (p[i] == null) { + return; + } + } + } + new CA (p, false); + new CA (p, true); + } + } + + private boolean attached = false; + + private class CA implements ChangeListener { + JScrollPane[] p; + BoundedRangeModel[] mdls; + boolean vert; + public CA (JScrollPane[] p, boolean vert) { + this.vert = vert; + this.p = p; + for (int i=0; i < p.length; i++) { + if (p[i] == null) { + return; + } + } + init(); + attached = true; + } + + private void init() { + mdls = new BoundedRangeModel[p.length]; + int val = 0; + int ext = 0; + for (int i=0; i < p.length; i++) { + mdls[i] = vert ? p[i].getVerticalScrollBar().getModel() : + p[i].getHorizontalScrollBar().getModel(); + if (vert) { + if (i == 0) { + val = mdls[i].getValue(); + ext = mdls[i].getExtent(); + } else { + val += ext; + mdls[i].setValue(val); + } + } + mdls[i].addChangeListener(this); } } - support.ensureAnnotationsLoaded(); + public void stateChanged(ChangeEvent e) { + int idx = Arrays.asList(mdls).indexOf(e.getSource()); + for (int i=0; i < mdls.length; i++) { + if (i != idx) { + int val = mdls[idx].getValue(); + if (vert) { + mdls[i].setValue(val + (mdls[idx].getExtent() * (i - idx))); + } else { + mdls[i].setValue(val); + } + } + } + } + } + + + public void doLayout() { + if (PANE_COUNT != 1) { + Component[] c = getComponents(); + Component tb = null; + Dimension tbDim = customToolbar == null ? new Dimension (0,0) : + customToolbar.getPreferredSize(); + Insets ins = getInsets(); + int left = ins.left; + int x = left; + int top = ins.top + tbDim.height; + int height = getHeight() - (top + ins.bottom); + int w = (getWidth() - ins.left + ins.right) / PANE_COUNT; + for (int i=0; i < PANE_COUNT; i++) { + if (comps[i] != null) { + comps[i].setBounds(x, top, w, height); + } + x += w; + } + if (customToolbar != null) { + customToolbar.setBounds (ins.top, ins.left, tbDim.width, tbDim.height); + } + } else { + super.doLayout(); + } } protected CloneableTopComponent createClonedObject() { @@ -441,6 +567,10 @@ * @see #componentDeactivated */ protected void componentActivated() { support.setLastSelected(this); + if (!attached) { + System.err.println("DOING IT"); + SwingUtilities.invokeLater(new R()); + } } /** Updates the name and tooltip of this CloneableEditor