pivot-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Schwartz, Cynthia L" <cynthia.l.schwa...@intel.com>
Subject RE: Does Pivot support dockable windows?
Date Wed, 06 Feb 2013 17:44:06 GMT
Oliver and Roger,

This is fantastic.  Thank  you very much, I will be able to try it out in the next few days.

Cynthia

From: Oliver Oyston [mailto:Oliver.Oyston@actian.com]
Sent: Tuesday, February 05, 2013 4:10 PM
To: user@pivot.apache.org
Subject: RE: Does Pivot support dockable windows?

So, you can implement a "mock" docking window interface that approximates the docking functionality
of Visual Studio fairly easily. However, there are limitations: you can't reposition / drag
/ drop or float the "windows" and you don't get dock guides or to use advanced layout options.
For many purposes this could be sufficient.

When I implemented docking / MDI interface for a product we are developing, I used a combination
of TabPanes / SpliPanes for the tool windows and logic for hiding/showing/closing as appropriate.

We have an "Object Explorer" tool window that is permanently docked to the left and an "Output"
tool window that is permanently docked to the bottom. The tool windows have a pin and a close
button.

Here is some sample code - I'd suggest creating a sample application, replace the images with
your own and have a "play" and see how it all hangs together. Once you understand how it hangs
together you should be fairly easily able to customize it for your own needs.

Imports:

import org.apache.pivot.beans.BXML;
import org.apache.pivot.serialization.SerializationException;
import org.apache.pivot.wtk.Button;
import org.apache.pivot.wtk.ButtonPressListener;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.ComponentMouseButtonListener;
import org.apache.pivot.wtk.Mouse;
import org.apache.pivot.wtk.PushButton;
import org.apache.pivot.wtk.SplitPane;
import org.apache.pivot.wtk.TabPane;

Code Behind:

    /**
     * The main split bar of the application.
     */
    @BXML
    private SplitPane mainSplitter;

    /**
     * The output tool window tab pane.
     */
    @BXML private TabPane outputToolWindowTabPane;

    /**
     * The output tool window split pane.
     */
    @BXML private SplitPane outputToolWindowSplitPane;

    /**
     * The output tool window pin button.
     */
    @BXML private PushButton outputToolWindowPinPushButton;

    /**
     * The output tool window close button.
     */
    @BXML private PushButton outputToolWindowClosePushButton;

    /**
     * The object explorer tool window tab pane.
     */
    @BXML private TabPane objectExplorerToolWindowTabPane;

    /**
     * The object explorer tool window pin button.
     */
    @BXML private PushButton objectExplorerToolWindowPinPushButton;

    /**
     * The object explorer tool window close button.
     */
    @BXML private PushButton objectExplorerToolWindowClosePushButton;

    /**
     * The state that the object explorer tool window is currently in.
     */
    private ToolWindowState objectExplorerToolWindowState = ToolWindowState.OPEN;

    /**
     * The state that the output tool window is currently in.
     */
    private ToolWindowState outputToolWindowState = ToolWindowState.COLLAPSED;

    /**
     * An enumeration of the possible tool window states.
     */
    public enum ToolWindowState
    {
        /**
         * The tool window is open.
         */
        OPEN,

        /**
         * The tool window is collapsed.
         */
        COLLAPSED,

        /**
         * The tool window is closed.
         */
        CLOSED
    }

    private float objectExplorerSplitRatio = 0;
    private float outputToolWindowSplitRatio = 0;

    /**
     * An enumeration of the available tool windows.
     */
    public enum ToolWindow
    {
        /**
         * The object explorer tool window.
         */
        OBJECT_EXPLORER,

        /**
         * The output tool window.
         */
        OUTPUT,
    }

    private class ToolWindowButtonListener implements ButtonPressListener
    {
        private ToolWindow window;
        private ToolWindowState state;

        public ToolWindowButtonListener(ToolWindow window, ToolWindowState state) {
            this.window = window;
            this.state = state;
        }
        @Override
        public void buttonPressed(Button button) {
            setToolWindowToState(window, state);
        }
    }

    /**
     * Instantiate a window button listener.
     */
    private void addWindowButtonListener(Button button, ToolWindow window, ToolWindowState
state) {
        button.getButtonPressListeners().add(new ToolWindowButtonListener(window, state));
    }

    /**
     * Sets the state of a tool window.
     *
     * @param toolWindow The tool window.
     * @param state The state that we wish to set the tool window to.
     */
    public void setToolWindowToState(ToolWindow toolWindow, ToolWindowState state){

        // If we are dealing with the output window and it is already in the required state
then do nothing
        if ((toolWindow == ToolWindow.OUTPUT) && (state == outputToolWindowState)){
            return;
        }

        // If we are dealing with the object explorer window and it is already in the required
state then do nothing
        if ((toolWindow == ToolWindow.OBJECT_EXPLORER) && (state == objectExplorerToolWindowState)){
            return;
        }

        // Initialize variables as appropriate
        SplitPane splitPane = null;
        TabPane tabPane = null;
        int closedSplitRatio = 0;
        float openSplitRatio = 0;

        // Amend variables as appropriate for the tool window
        switch (toolWindow) {
            case OBJECT_EXPLORER:
                objectExplorerToolWindowState = state;
                splitPane = mainSplitter;
                tabPane = objectExplorerToolWindowTabPane;
                closedSplitRatio = 0;
                openSplitRatio = objectExplorerSplitRatio;
                break;
            case OUTPUT:
                outputToolWindowState = state;
                splitPane = outputToolWindowSplitPane;
                tabPane = outputToolWindowTabPane;
                closedSplitRatio = 1;
                openSplitRatio = outputToolWindowSplitRatio;
                break;
        }

        // Perform the required action
        switch (state) {
            case OPEN:
                hideToolWindowTabPane(tabPane);
                showToolPane(splitPane, openSplitRatio);
                break;
            case COLLAPSED:
                outputToolWindowSplitRatio = outputToolWindowSplitPane.getSplitRatio();
                objectExplorerSplitRatio = mainSplitter.getSplitRatio();
                hideToolPane(splitPane, closedSplitRatio);
                showToolWindowTabPane(tabPane);
                break;
            case CLOSED:
                outputToolWindowSplitRatio = outputToolWindowSplitPane.getSplitRatio();
                objectExplorerSplitRatio = mainSplitter.getSplitRatio();
                hideToolPane(splitPane, closedSplitRatio);
                hideToolWindowTabPane(tabPane);
                break;
        }
    }

    /**
     * Shows a tab pane.
     *
     * @param tabPane The tab pane to show.
     */
    private void showToolWindowTabPane(TabPane tabPane) {
        tabPane.setVisible(true);
    }

    /**
     * Hides a tool pane.
     *
     * @param splitPane The split pane that houses the tool pane.
     * @param splitRatio The split ratio that corresponds to hidden.
     */
    private void hideToolPane(SplitPane splitPane, int splitRatio) {

        // Set the split pane to the specified ratio
        splitPane.setSplitRatio(splitRatio);

        // Set the styles on the split pane.
        try {
            splitPane.setStyles("{splitterHandlePrimaryColor:'#0000F0',splitterThickness:0}");
        } catch (SerializationException e) {
            e.printStackTrace();
        }

        // Lock the split pane.
        splitPane.setLocked(true);
    }

    /**
     * Hides a tool window tab pane.
     *
     * @param tabPane The tab pane to hide.
     */
    private void hideToolWindowTabPane(TabPane tabPane) {
        tabPane.setVisible(false);
    }

    /**
     * Shows a tool pane.
     *
     * @param splitPane The split pane that houses the tool window.
     * @param splitRatio The split ratio that corresponds to the tool pane been shown.
     */
    private void showToolPane(SplitPane splitPane, float splitRatio) {

        // Set the split ration.
        splitPane.setSplitRatio(splitRatio);

        // Set the style for the split pane.
        try {
            splitPane.setStyles("{splitterHandlePrimaryColor:'#0000F0',splitterThickness:6}");
        } catch (SerializationException e) {
            e.printStackTrace();
        }

        // Unlock the split pane.
        splitPane.setLocked(false);
    }

    /**
     * Mouse button listener for a tool window.
     */
    private class ToolWindowComponentMouseButtonListener implements ComponentMouseButtonListener
{

        // The tool window that the listener is for.
        private ToolWindow toolWindow;

        /**
         * Initializes a new instance of the class.
         *
         * @param toolWindow The tool window that the listener corresponds to.
         */
        public ToolWindowComponentMouseButtonListener(ToolWindow toolWindow){
            super();
            this.toolWindow = toolWindow;
        }

        /**
         * Mouse down event for the tool window tab pane.
         *
         * @param component The component.
         * @param button The mouse button that has gone down.
         * @param x The 'x' coordinate of the mouse down.
         * @param y The 'y' coordinate of the mouse down.
         * @return Whether the event has been handled.
         */
        @Override
        public boolean mouseDown(Component component, Mouse.Button button, int x, int y) {

            // Get the tab pane.
            TabPane tabPane = (TabPane)component;

            // Get the component at the location of the mouse down.
            Component comp = tabPane.getComponentAt(x, y);

            /**
             * If we don't have a component then return.
             */
            if(comp == null){
                return true;
            }

            // We have a component so this must be the 'button' so set the tool window to
open.
            setToolWindowToState(toolWindow, ToolWindowState.OPEN);

            // return handled
            return true;
        }

        @Override
        public boolean mouseUp(Component component, Mouse.Button button, int x, int y) {
            // No specific implementation required.
            return false;
        }

        @Override
        public boolean mouseClick(Component component, Mouse.Button button, int x, int y,
int count) {
            // No specific implementation required.
            return false;
        }
    }

And hooking everything up in  the constructor:

         // Hook up the window buttons
         addWindowButtonListener(outputToolWindowPinPushButton, ToolWindow.OUTPUT, ToolWindowState.COLLAPSED);
         addWindowButtonListener(objectExplorerToolWindowPinPushButton, ToolWindow.OBJECT_EXPLORER,
ToolWindowState.COLLAPSED);
         addWindowButtonListener(outputToolWindowClosePushButton, ToolWindow.OUTPUT, ToolWindowState.CLOSED);
         addWindowButtonListener(objectExplorerToolWindowClosePushButton, ToolWindow.OBJECT_EXPLORER,
ToolWindowState.CLOSED);

         objectExplorerSplitRatio = 0.25f;
         outputToolWindowSplitRatio = 0.7f;

         mainSplitter.setPrimaryRegion(SplitPane.Region.TOP_LEFT);

         setToolWindowToState(ToolWindow.OBJECT_EXPLORER, ToolWindowState.OPEN);


         // Add listener to the output tool window tab pane
         outputToolWindowTabPane.getComponentMouseButtonListeners().add(new ToolWindowComponentMouseButtonListener(ToolWindow.OUTPUT));

         // Add listener to the object explorer tool window tab pane
         objectExplorerToolWindowTabPane.getComponentMouseButtonListeners().add(new ToolWindowComponentMouseButtonListener(ToolWindow.OBJECT_EXPLORER));

The bxml is as follows:

<?xml version="1.0" encoding="utf-8"?>
<Window title="%mainAppTitle"
    maximized="true"
     bxml:id="mainWindow"
     xmlns:bxml="http://pivot.apache.org/bxml"
     xmlns:content="org.apache.pivot.wtk.content"
     xmlns="org.apache.pivot.wtk">
  <!-- Main window content -->
  <content>
    <TablePane>
      <columns>
        <TablePane.Column width="1*" />
      </columns>
      <rows>
      <!-- Main Row -->
        <TablePane.Row height="1*">
          <SplitPane bxml:id="outputToolWindowSplitPane" orientation="vertical" splitRatio="1"
locked="true" styles="{splitterHandlePrimaryColor:'#0000F0',splitterThickness:0}">
            <left>
              <TablePane>
                <columns>
                  <TablePane.Column width="-1" />
                  <TablePane.Column width="1*" />
                </columns>
                <rows>
                  <TablePane.Row height="1*">
                    <BoxPane styles="{backgroundColor:'#E8E8E8'}">
                      <TabPane bxml:id="objectExplorerToolWindowTabPane" collapsible="true"
selectedIndex="-1" visible="false" styles="{backgroundColor:'#FFFFFF',tabOrientation:'vertical',
activeTabColor:'#F7F5EE', inactiveTabColor:'#F7F5EE'}">
                        <BoxPane>
                          <TabPane.tabData>
                            <content:ButtonData text="%titleInstanceExplorer" icon="@/images/obj-expl-16.png"
/>
                          </TabPane.tabData>
                        </BoxPane>
                      </TabPane>
                    </BoxPane>
                    <SplitPane bxml:id="mainSplitter" splitRatio="0.30" styles="{splitterHandlePrimaryColor:'#0000F0'}">
                      <left>
                        <Border styles="{color:10}">
                          <content>
                            <TablePane>
                              <columns>
                                <TablePane.Column width="1*" />
                              </columns>
                              <TablePane.Row height="1*">
                                <TablePane>
                                  <columns>
                                    <TablePane.Column width="1*" />
                                  </columns>
                                  <rows>
                                    <TablePane.Row height="-1">
                                      <TablePane>
                                        <columns>
                                          <TablePane.Column width="-1" />
                                          <TablePane.Column width="1*" />
                                        </columns>
                                        <rows>
                                          <TablePane.Row>
                                            <BoxPane orientation="horizontal" styles="{padding:2,
fill:true}">
                                              <Label text="%titleObjectExplorer" styles="{color:'#ffffff',font:{bold:true}}"
/>
                                            </BoxPane>
                                            <BoxPane orientation="horizontal" styles="{padding:0,
fill:true, horizontalAlignment:'right'}">
                                              <PushButton bxml:id="objectExplorerToolWindowPinPushButton"
styles="{toolbar:true}" tooltipText="%tipAutoHide">
                                                <buttonData>
                                                  <content:ButtonData icon="@/images/winpin-14.png"
/>
                                                </buttonData>
                                              </PushButton>
                                              <PushButton bxml:id="objectExplorerToolWindowClosePushButton"
styles="{toolbar:true}" tooltipText="%tipClose">
                                                <buttonData>
                                                  <content:ButtonData icon="@/images/winclose-14.png"
/>
                                                </buttonData>
                                              </PushButton>
                                            </BoxPane>
                                          </TablePane.Row>
                                        </rows>
                                      </TablePane>
                                    </TablePane.Row>
                                    <TablePane.Row height="1*">
                                        <!-- Left docked tool window content -->
                                    </TablePane.Row>
                                  </rows>
                                </TablePane>
                              </TablePane.Row>
                            </TablePane>
                          </content>
                        </Border>
                      </left>
                      <right>
                          <!-- Main content here -->
                      </right>
                    </SplitPane>
                  </TablePane.Row>
                </rows>
              </TablePane>
            </left>
            <right>
              <Border styles="{color:10}">
                <content>
                  <TablePane>
                    <columns>
                      <TablePane.Column width="1*" />
                    </columns>
                    <rows>
                      <TablePane.Row height="-1">
                        <TablePane>
                          <columns>
                            <TablePane.Column width="1*" />
                            <TablePane.Column width="-1" />
                          </columns>
                          <rows>
                            <TablePane.Row>
                              <BoxPane orientation="horizontal" styles="{padding:2, fill:true}">
                                <Label text="%titleOutputWindow" styles="{color:'#ffffff'}"
/>
                              </BoxPane>
                              <BoxPane orientation="horizontal" styles="{padding:0, fill:true}">
                                <PushButton bxml:id="outputToolWindowPinPushButton" styles="{toolbar:true}"
tooltipText="%tipAutoHide">
                                  <buttonData>
                                    <content:ButtonData icon="@/images/winpin-14.png" />
                                  </buttonData>
                                </PushButton>
                                <PushButton bxml:id="outputToolWindowClosePushButton" styles="{toolbar:true}"
tooltipText="%tipClose">
                                  <buttonData>
                                    <content:ButtonData icon="@/images/winclose-14.png"
/>
                                  </buttonData>
                                </PushButton>
                              </BoxPane>
                            </TablePane.Row>
                          </rows>
                        </TablePane>
                      </TablePane.Row>
                      <TablePane.Row height="1*">
                          <!-Bottom docked tool window content -->
                      </TablePane.Row>
                    </rows>
                  </TablePane>
                </content>
              </Border>
            </right>
          </SplitPane>
        </TablePane.Row>
        <!-- Output Tool Pane -->
        <TablePane.Row height="-1">
          <TabPane bxml:id="outputToolWindowTabPane" collapsible="true" selectedIndex="-1"
styles="{backgroundColor:'#E8E8E8'}">
            <BoxPane>
              <TabPane.tabData>
                <content:ButtonData text="%titleOutputWindow" icon="@/images/output-16.png"
/>
              </TabPane.tabData>
            </BoxPane>
          </TabPane>
        </TablePane.Row>
      </rows>
    </TablePane>
  </content>
</Window>

You could implement floating windows (we have not) but it certainly not trivial to do...

Hope this helps.

Oliver

From: Roger L. Whitcomb [mailto:Roger.Whitcomb@actian.com]
Sent: Tuesday, February 05, 2013 9:38 AM
To: user@pivot.apache.org<mailto:user@pivot.apache.org>
Subject: RE: Does Pivot support dockable windows?

It is not the same as in Swing - I'll have to check with the developer who did that work on
our product.

~Roger

From: Schwartz, Cynthia L [mailto:cynthia.l.schwartz@intel.com]
Sent: Monday, February 04, 2013 4:18 PM
To: user@pivot.apache.org<mailto:user@pivot.apache.org>
Subject: RE: Does Pivot support dockable windows?

Roger,

Yes eventually I would need floating windows.  How do you accomplish dockable windows, is
it similar to getting docking windows in Swing?

Thanks,
Cynthia

From: Schwartz, Cynthia L
Sent: Monday, February 04, 2013 10:09 AM
To: user@pivot.apache.org<mailto:user@pivot.apache.org>
Subject: Does Pivot support dockable windows?

And if so, is there an example?

Thanks,
Cynthia

Mime
View raw message