Thanks for the clarification and notes.
As promised, attached you will find a zip with my solution I mentioned earlier. To my surprise, it turned out simpler than I first thought, mainly due to the fact that all of the code was already available out there – I just needed to find it! And yes – saving the current perspective is exactly as you described it (DockFrontend.save()). In addition, I even managed to add an extra functionality (“Reset” default perspective) that is accessible from a menu – similar to the reset default perspective feature in Eclipse. So, in short, whilst there are a couple of tiny bits I would like to tweak (we can discuss these if time allows), I am really pleased with the outcome so far. Naturally, I will wait for your and the community’s feedback to assess the merits of this solution.
Solution:
Keep in mind the solution consists of two parts:
a- Saves the current perspective, including any layout changes, closing, and additions of dockables. It does this when switching between one perspective and another, and keeps on doing it automatically without user intervention (i.e. no dialogue prompts).
b- Resets the current perspective back to its “Default” setting. This is done via the user menu system.
Installation and Set-up:
A working example of the complete solution is attached in this posting, which contain detailed code annotations to help describe the solution.
1- Class module(s): At minimum, one class is required; PerspectiveManager. This defines routine calls for both parts of the solution.
Optionally, a second class, PerspectiveSnapshot, can be used if the developer wishes to override (or add) methods in one of DF’s classes (namely, the super class FrontendSettingsMenuPiece). Since I plan to deploy a different dialogue than the one currently defined in FrontendSettingsMenuPiece, I have opted to implement PerspectiveSnapshot as a flexible utility class for future customisation to my tool. Clearly, the developer will need to reference FrontendSettingsMenuPiece instead of PerspectiveSnapshot within PerspectiveManager.
**PerspectiveManager **looks like this:
import java.awt.Component;
import java.awt.event.ActionEvent;
import com.df.DFWelcome;
import com.df.util.PerspectiveSnapshot;
import bibliothek.gui.DockFrontend;
import bibliothek.gui.dock.common.CControl;
public class PerspectiveManager {
//Define your preferred way to declare CControl.
private static CControl dockControl = DFWelcome.getDockControl();
private static PerspectiveSnapshot perspectiveSnapshot = null;
//Optional: Useful for associating directly with a component such as a JMenuItem or JButton, among others.
public static void updatePerspectiveSnapshot(Component owner) {
initializePerspectiveSnapshot();
perspectiveSnapshot.save(owner);
}
//Mandatory: In almost all cases, you will use this method called by the appropriate listener to save a snapshot of the
//current perspective (i.e. the perspective you are on) immediately before the user switches to another perspective.
//This method saves any changes to the perspective the user may have made, and should look the same on the next visit.
//Note: changes to MultipleCDockables, such as editor files, behave differently than SingleCDockables, i.e. any editor
//files created after the previous snapshot will be carried over to the previous snapshot. This behaviour is in keeping
//with Eclipse.
public static void updatePerspectiveSnapshot(ActionEvent evIn) {
initializePerspectiveSnapshot();
perspectiveSnapshot.save((Component) evIn.getSource());
}
//Optional: Reset the current perspective back to its Default setting. Note: you will need to add the extra "Reset" perspective
//setting (one line of code) when defining the original layout perspective for this functionality to work. See InitializeSingleCDock
//and InitializeMultipleCDock classes in this app example.
public static void resetPerspectiveSnapshot(ActionEvent evIn, DockFrontend dockFrontendIn) {
initializePerspectiveSnapshot();
//List the perspectives that should participate in Reset functionality.
if (("welcomePerspective").equals(dockFrontendIn.getCurrentSetting())) {
dockControl.load("welcomePerspectiveReset");
perspectiveSnapshot.getFrontend().setSetting("welcomePerspective",
perspectiveSnapshot.getFrontend().getSetting("welcomePerspectiveReset"));
dockControl.load("welcomePerspective");
}
else if (("editorPerspective").equals(dockFrontendIn.getCurrentSetting())) {
dockControl.load("editorPerspectiveReset");
perspectiveSnapshot.getFrontend().setSetting("editorPerspective",
perspectiveSnapshot.getFrontend().getSetting("editorPerspectiveReset"));
dockControl.load("editorPerspective");
}
//Define any additional perspectives using the above templates...
}
//Grabs all perspectives out there that are known by DockFrontend.
public static DockFrontend getPerspectives() {
initializePerspectiveSnapshot();
return perspectiveSnapshot.getFrontend();
}
//Creates PerspectiveSnapshot object if it is missing. There should only be one at any given one time.
private static void initializePerspectiveSnapshot() {
if (perspectiveSnapshot == null) {
perspectiveSnapshot = new PerspectiveSnapshot(dockControl, false);
}
}
}
2- Set-up: This is for setting-up part ‘b’ of the solution. A line of code is all that is required to set-up the ‘Reset’ functionality for each layout perspective definition. It is probably best to define it at same time as the original layout (aka. ‘Default’) perspective. In the attached app, the single line looks like this (refer to InitializeSingleCDock and InitializeMultipleCDock classes):
perspectives.setPerspective(“welcomePerspectiveReset”, welcomePerspective);
A perspective definition may look like this:
perspectives = dockControl.getPerspectives();
CPerspective welcomePerspective = perspectives.createEmptyPerspective();
CGridPerspective gridPerspective = welcomePerspective.getContentArea().getCenter();
gridPerspective.gridAdd(0,0,6,10, new SingleCDockablePerspective("welcomeDockID"));
gridPerspective.gridAdd(6,0,6,10, new SingleCDockablePerspective("newsDockID"));
//Set your perspective (i.e. initial layout) in the usual way. Call this the 'Default' perspective.
perspectives.setPerspective("welcomePerspective", welcomePerspective);
//Optional: For each Default perspective definition, set a secondary unique perspective if you wish to enable the user to reset
//back to the default perspective at any point during runtime. Call this the 'Reset' perspective.
//If you do not define this line, you will deactivate the ability to reset the default perspective, but Docking Frames will still
//continue to track and save the latest changes made to the perspective. Essentially, the Reset setting is a copy of the Default
//setting, i.e. each layout perspective has a pair of saved perspectives in the framework. It may help if you append 'Reset' in
//the name.
perspectives.setPerspective("welcomePerspectiveReset", welcomePerspective);
//Do not load perspective yet. The load order is controlled in DFMain initially, and later in PerspectiveManager during runtime.
//dockControl.load("welcomePerspective");
}
3- Implementation:
To save the updated current perspective, insert the following two lines within a listener /event handler:
PerspectiveManager.updatePerspectiveSnapshot(evIn);
dockControl.load(“welcomePerspective”);
My app implements the ‘Welcome’ perspective like this:
btnWelcome = new JButton("Welcome");
btnWelcome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evIn) {
//Call to save a snapshot of the current perspective (i.e. saves any changes to the perspective the user made).
PerspectiveManager.updatePerspectiveSnapshot(evIn);
dockControl.load("welcomePerspective");
}
});
toolBar.add(btnWelcome);```
And for the ‘Editor’ perspective like this:
``` //JButton: "Editor"
btnEditor = new JButton("Editor");
btnEditor.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evIn) {
//Call to save a snapshot of the current perspective (i.e. saves any changes to the perspective the user made).
PerspectiveManager.updatePerspectiveSnapshot(evIn);
dockControl.load("editorPerspective");
}
});
toolBar.add(btnEditor);```
To reset the current perspective back to the default, insert the following line within the appropriate listerner /event handler:
**PerspectiveManager.resetPerspectiveSnapshot(evIn, PerspectiveManager.getPerspectives());**
In my app, it looks like this:
``` //JMenuItem: "Reset Perspective...".
//Optional: Create menu item in order to reset back to the Default perspective. Note: For this to work, you will need to include
//the 'Reset' perspective line at the point of defining your Default layout perspective (refer to InitializeSingleCDock and
//InitializeMultipleCDock classes in this app example).
final JMenuItem mntmResetPerspective = new JMenuItem("Reset Perspective...");
mntmResetPerspective.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evIn) {
//We pass all known perspectives by calling PerspectiveManager.getPerspectives(). Hopefully, our current
//perspective is included in the list (within DockFrontend).
PerspectiveManager.resetPerspectiveSnapshot(evIn, PerspectiveManager.getPerspectives());
}
});```
**4- All done.**
**Test Scenario: Saving current perspective (when toggling between perspectives)**
1- Launch the app.
2- Welcome perspective displays, showing Welcome and News dockables. Changes the position or layout of the dockables.
3- Click File > Open Help. You should see the newly created ‘Help 1’ dockable display within the current perspective (the position will depend on the changes you made to the dockables earlier). Feel free to continue making changes, include creating additional new Help dockables.
4- Now click Editor menu button. This displays the Editor perspective, showing dockables for West, East and an empty Workingarea in the middle.
5- Make any position or layout changes you wish. Next, click File > New File. This displays the newly created editor file. You can even create Help dockables if so desired. Continue to make additional changes as desired, even creating more editor files.
6- Now click the Welcome menu button. You should see the Welcome perspective display in the same state as you left in your last visit.
7- Click the Editor menu button. You should see the Editor perspective display also in the same state as you left in your previous visit. One note: Editor files (i.e. MultipleCDockables) dockables behave differently than West, East (and Help) dockables (i.e. SingleCDockables) in that the editor files are user-specific and the framework should keep them at all times. This makes sense since a user would expect his /her open editor files to be maintained. This behaviour is the same in Eclipse.
8- Continue this cycle of switching between perspectives and making changes as you go along. You should (hopefully) see the app keeping up with updating the state of the perspective.
**Test Scenario: Resetting back to Default perspective**
1- Follow same 1 – 6 steps above (you should be in the Welcome perspective).
2- Click Perspective main menu button > Reset Perspective. You should see the Default Welcome perspective display showing the original layout.
3- Now click the Editor menu button. In the Editor perspective, click Perspective > Reset Perspective. You should see the Default Editor perspective showing, with the exception of any open editor files. Specifically, the layout of West, East, and Workingarea dockables should mach their Default definitions. Again, as noted earlier, any open user-specific editor files should always display as this would be the expected behaviour.
Hope this helps others looking for a similar solution.
Any feedback, comments, etc, are welcome.
/Adi