2

I want to create a Qooxdoo application that consists of a Desktop with multiple Windows. The Desktop (and not each Window) also has a (common) ToolBar.
Now I want to have a command to "save" the document of the active window. This command can be triggered by the keyboard shortcut "Ctrl+S" as well as a button on the toolbar.

To handle the "Ctrl+S" to reach the currently active window the qx.ui.command.GroupManager (as described by https://qooxdoo.org/documentation/v7.5/#/desktop/gui/interaction?id=working-with-commands and https://qooxdoo.org/qxl.demobrowser/#ui~CommandGroupManager.html) is supposed to be the best solution. And I could easily implement that in my code.

But now I'm struggling to make the toolbar save button also call the save command of the currently active window as I don't know how to bind it correctly to the GroupManager.

An example code to get started in the playground https://qooxdoo.org/qxl.playground/:

// NOTE: run this script only once. Before running it again you need to reload
// the page as it seems that the commands are accumulation and not reset.
// I guess that this is a bug in the Playground

const root = this.getRoot();

qx.Class.define('test.Application',
{
  extend : qx.application.Standalone,
  members: {
    main: function() {
      const layout = new qx.ui.layout.VBox(5);
      const container = new qx.ui.container.Composite(layout);
      root.add(container, {edge: 0});
      const windowManager = new qx.ui.window.Manager();
      const desktop = new qx.ui.window.Desktop(windowManager);

      this._manager = new qx.ui.command.GroupManager();
      
      const menuBar = new qx.ui.menubar.MenuBar();
      let menu = new qx.ui.menu.Menu();
      
      ///////////////////////////
      // TODO: Call _doSave() of the active window!
      let saveMenuButton = new qx.ui.menu.Button('Save','@MaterialIcons/save/16');
      ///////////////////////////
      
      menu.add(saveMenuButton);
      var fileMenu = new qx.ui.menubar.Button('File', null, menu);
      menuBar.add(fileMenu);
      const toolBar = new qx.ui.toolbar.ToolBar();
      
      ///////////////////////////
      // TODO: Call _doSave() of the active window!
      let saveToolBarButton = new qx.ui.toolbar.Button('Save','@MaterialIcons/save/16');
      ///////////////////////////
      
      toolBar.add(saveToolBarButton);
      container.add(menuBar,{flex:0});
      container.add(toolBar,{flex:0});
      container.add(desktop,{flex:1});
      
      this._foo1 = new test.Window('foo1', this);
      desktop.add(this._foo1);
      this._foo1.open();
      this._foo1.moveTo(100,20);
      
      this._foo2 = new test.Window('foo2', this);
      desktop.add(this._foo2);
      this._foo2.open();
      this._foo2.moveTo(200,100);

      this._foo3 = new test.Window('foo3', this);
      desktop.add(this._foo3);
      this._foo3.open();
      this._foo3.moveTo(300,180);
    },
    getGroupManager() {
      return this._manager;
    }
  }
});

qx.Class.define('test.Window', {
  extend: qx.ui.window.Window,
  construct(windowName, controller) {
    this.base(arguments, windowName);
    this._name = windowName;
    
    let commandGroup = new qx.ui.command.Group();
    const cmd = new qx.ui.command.Command("Ctrl+S");
    cmd.addListener('execute', this._doSave, this);
    commandGroup.add('save', cmd);
    controller.getGroupManager().add(commandGroup);
    this.addListener('changeActive', () => {
      if (this.isActive()) {
        controller.getGroupManager().setActive(commandGroup);
      }
    }, this);
  },
  members: {
    _doSave() {
      alert("save " + this._name);
    }
  }
});

a = new test.Application();

How should the saveMenuButton.setCommand() and saveToolBarButton.setCommand() should look like to always call the command of the active window?

Chris
  • 3,265
  • 5
  • 37
  • 50
  • could you attach minimal code example to reproduce the problem and possible to run it on the playground? – goldim Feb 13 '23 at 09:00
  • 1
    The playground URL shortener didn't work, so I had to copy the content in the edit of the question. – Chris Feb 13 '23 at 21:59

1 Answers1

1

You can control a current active window via Desktop class:

let saveToolBarButton = new qx.ui.toolbar.Button('Save');
saveToolBarButton.addListener("click", function(){
  desktop.getActiveWindow()._doSave();
}, this);

Would be great for your solution imo is to create a separate command and add this command to buttons:

const saveActiveWindowCommand = new qx.ui.command.Command();
saveActiveWindowCommand.addListener("execute", function(){
  desktop.getActiveWindow()._doSave();
}, this);

let saveMenuButton = new qx.ui.menu.Button('Save');
saveMenuButton.setCommand(saveActiveWindowCommand);

let saveToolBarButton = new qx.ui.toolbar.Button('Save');
saveToolBarButton.setCommand(saveActiveWindowCommand);

EDIT: You could set commands dynamically for "Main Panel" menu buttons. Because there is only one instance of command pressing "Ctrl+S" will trigger only one command but maybe you would like that main bar save buttons have extra logic. You have in application class next method which will be called from window class when changeActive event happens.

    setSaveCommand(command){
      this.saveMenuButton.setCommand(command);
      this.saveToolBarButton.setCommand(command);
    },

and in your Window class:

      if (this.isActive()) {
        controller.setSaveCommand(cmd);
        controller.getGroupManager().setActive(commandGroup);
      }
goldim
  • 466
  • 1
  • 3
  • 13
  • Generally I like your second solution. But it comes with a problem: the menu bar entry doesn't show the hot key `Ctrl+S` for the entry. And adding it to the command makes it called twice. Of course I can now delete the `commandGroup.add('save', cmd);` in the `test.Window` class. But then I don't need the `qx.ui.command.Group()` at all anymore. So is it right, that I should remove the `commandGroup` as it isn't useful in this case? – Chris Feb 15 '23 at 21:32
  • Actually, there is a lot of solutions which depends on what exactly you want to do and your application. I may suggest another one which is based on changing commands in main menu buttons. – goldim Feb 16 '23 at 09:57