FindReplaceOverlay: share search settings per editor stack#1
Conversation
Editors in the same tab group now share a common find/replace state. Switching between tabs in a stack keeps the overlay in sync: it auto-opens on the newly activated editor and auto-closes when another stack-mate closes it. Independent stacks (e.g. side-by-side editors) maintain their own separate settings. Fixes: eclipse-platform#2055
| IWorkbenchPartSite site = targetPart.getSite(); | ||
| if (site == null) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
getSite() sollte zu diesem Zeitpunkt nicht mehr null sein dürfen, da die Initialisierung vom Part schon abgeschlossen sein muss
| if (isRestoringSettings) { | ||
| return; | ||
| } |
There was a problem hiding this comment.
Das hier finde ich nicht so schön gelöst.
Dieser isRestoringSettings-Guard ist ja nach meinem Verständnis nur notwendig ist, weil dieser in applyStackSettings von searchBar.setText(...) sonst nochmal aufgerufen werden würde (hier wäre übrigens ein Kommentar hilfreich, ohne zu Debuggen ist sonst kaum zu erkennen, wofür das gedacht ist).
Den Check dafür würde ich daher nicht hier, sondern im ModifyListener der Searchbar einbauen (mit Kommentar).
Am besten wäre es natürlich den Textinhalt der Searchbar wiederherzustellen, ohne dabei ein Update auszulösen. @HeikoKlare Hast du noch Ideen, was man hier machen könnte?
| private void openForStack() { | ||
| if (!containerControl.isVisible()) { | ||
| containerControl.setVisible(true); | ||
| bindListeners(); | ||
| restoreOverlaySettings(); | ||
| setOverlayOpenInStack(true); | ||
| registerStackMemberActivationListener(); | ||
| } | ||
| assignIDs(); | ||
| containerControl.layout(); | ||
| containerControl.moveAbove(null); | ||
| updatePlacementAndVisibility(); | ||
| updateContentAssistAvailability(); | ||
|
|
||
| searchBar.setFocus(); | ||
| } |
There was a problem hiding this comment.
Der Code ist fast identisch mit der open()-Methode -> als open(boolean forStack) kombinieren
| private void silentClose() { | ||
| if (containerControl.isDisposed() || !containerControl.getVisible()) { | ||
| return; | ||
| } | ||
| setOverlayOpenInStack(false); | ||
| storeOverlaySettings(); | ||
| findReplaceLogic.activate(SearchOptions.GLOBAL); | ||
| unbindListeners(); | ||
| containerControl.setVisible(false); | ||
| } |
There was a problem hiding this comment.
Der Code ist fast identisch mit der close()-Methode -> als close(boolean silently) kombinieren
| @Override | ||
| public void partDeactivated(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partOpened(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partClosed(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partHidden(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partVisible(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partBroughtToTop(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partInputChanged(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
| } |
There was a problem hiding this comment.
Evtl. könnte hier ein separates Issue erzeugt werden, um eine generische PartListenerAdapter-Klasse zu definieren.
@fedejeanne Was meinst du? Ich sehe keinen Grund, warum ein Verwender hier immer auf alle Part-Events reagieren sollte
There was a problem hiding this comment.
Man kann einfach die leere Methoden löschen, IPartListener2 hat bereits leere default-Methoden
| * always show the same search term and options, while independent editor stacks | ||
| * (e.g. side-by-side layouts) can carry different, unrelated search sessions. | ||
| */ | ||
| public class OverlaySearchSettings { |
There was a problem hiding this comment.
Das würde sich als Record meiner Meinung nach schöner abbilden lassen und ein HashCode/Equals gäbs dann auch noch gratis dazu :)
|
|
||
| private static final WeakHashMap<MPartStack, OverlaySearchSettings> STACK_SETTINGS = new WeakHashMap<>(); | ||
|
|
||
| private static final WeakHashMap<IWorkbenchPart, FindReplaceOverlay> PART_TO_OVERLAY = new WeakHashMap<>(); |
There was a problem hiding this comment.
Diese Felder würde ich nicht im Overlay selbst halten, sondern in eine Registry-Klasse auslagern
| settings.setReplaceBarOpen(false); | ||
|
|
||
| Accessor actionAccessor= new Accessor(getFindReplaceAction(), FindReplaceAction.class); | ||
| FindReplaceOverlay overlay= (FindReplaceOverlay) actionAccessor.get("overlay"); |
There was a problem hiding this comment.
Wenn du noch eine createForPart()-Methode ergänzen würdest, bei der die initialen Settings übergeben werden können, könnten die Reflection-Calls hier vermutlich vermieden werden
| shellToUse = fShell; | ||
| } | ||
| overlay = new FindReplaceOverlay(shellToUse, fWorkbenchPart, fTarget); | ||
| overlay = FindReplaceOverlay.getOrCreateForPart(shellToUse, fWorkbenchPart, fTarget); |
There was a problem hiding this comment.
Jetzt habe ich schon ziemlich viele Einzelkommentare gemacht, aber meiner Meinung nach könnte der Codefluss ab hier schon anders sein.
Design-Idee:
Die Action frägt bei einer FindReplaceOverlayRegistry an, ob zu einem bestimmten PartStack schon ein Overlay offen ist oder mal offen war. Wenn ja, wird die existierende Instanz zurückgegeben oder ein neue Instanz mit den gespeicherten Settings gebaut.
Wird eine solche Instanz jetzt aktiv vom Nutzer geschlossen (oder andersweitig disposed, z.B. durch Schließen des Editor-Tabs), werden die derzeitigen Settings für den PartStack gespeichert (falls dieser dann noch exisitiert).
Aus meiner Sicht gibts keinen Grund, dann noch bei jeder einzelnen Modifikation immer wieder die Settings zu speichern oder übersehe ich da etwas?
fedejeanne
left a comment
There was a problem hiding this comment.
Ich habe nicht getestet, nur den Code überflogen. Ich glaube mit den Kommentaren von Robin gibt es einiges zu tun bis zum nächsten Review.
Eine Sache nur: wir sollten uns abstimmen, ob wir in vi-eclipse auf Deutsch oder auf Englisch reviewen. Diese Orga ist public ;-)
| .withToolTipText(FindReplaceMessages.FindReplaceOverlay_upSearchButton_toolTip) | ||
| .withOperation(() -> performSearch(false)) | ||
| .withShortcuts(KeyboardShortcuts.SEARCH_BACKWARD).build(); | ||
| .withOperation(() -> performSearch(false)).withShortcuts(KeyboardShortcuts.SEARCH_BACKWARD).build(); |
There was a problem hiding this comment.
Auto-formattierung aktiv? Wenn möglich, bitte solche unnötige Änderungen vermeiden.
| @Override | ||
| public void partDeactivated(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partOpened(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partClosed(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partHidden(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partVisible(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partBroughtToTop(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
|
|
||
| @Override | ||
| public void partInputChanged(IWorkbenchPartReference partRef) { | ||
| /* unused */ } | ||
| } |
There was a problem hiding this comment.
Man kann einfach die leere Methoden löschen, IPartListener2 hat bereits leere default-Methoden




Editors in the same tab group now share a common find/replace state. Switching between tabs in a stack keeps the overlay in sync: it auto-opens on the newly activated editor and auto-closes when another stack-mate closes it.
Independent stacks (e.g. side-by-side editors) maintain their own separate settings.
Fixes: eclipse-platform#2055