Layout Managers
Posted: Thu Apr 12, 2018 2:16 am
Hi,
I noticed there are no window layout managers currently implemented (or I am blind and not finding them)
So I went ahead and made one for my own application. It appears to work really well in my case.
Wondering if this would be worthwhile incorporating into the core window manager?
(PS: some tidy up can be done, like changing the Boolean "VerHor" into an Enum and making the cascade offset settable, also, if this is internal, some of the checks and parameters, ie desktop, would not be needed and so on)
Hope this is useful.
Cheers.
Cheers.
I noticed there are no window layout managers currently implemented (or I am blind and not finding them)
So I went ahead and made one for my own application. It appears to work really well in my case.
Wondering if this would be worthwhile incorporating into the core window manager?
(PS: some tidy up can be done, like changing the Boolean "VerHor" into an Enum and making the cascade offset settable, also, if this is internal, some of the checks and parameters, ie desktop, would not be needed and so on)
Hope this is useful.
Cheers.
- Code: Select all
/*
* Copyright 2018 Wattsie.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.sibvisions.rad.ui.javafx.ext.mdi.FXDesktopPane;
import com.sibvisions.rad.ui.javafx.ext.mdi.FXInternalWindow;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Node;
/**
*
*/
public class FXInternalWindowLayout {
private static final Double CASCADE_PERCENT_WIDTH = 0.75;
private static final Double CASCADE_PERCENT_HEIGHT = 0.7;
private static final int CASCADE_OFFSET_X = 32;
private static final int CASCADE_OFFSET_Y = 32;
/**
* Rearrange windows in cascaded layout
*
* @param desktop
* @param IncludeMinimized
*/
public static void ArrangeFXIntWinInCascadeLayout(FXDesktopPane desktop, Boolean IncludeMinimized) {
ObservableList<FXInternalWindow> winndowsToBeResized = FXCollections.observableArrayList();
// Get all Window Nodes from our desktop
ObservableList<FXInternalWindow> windowNodes = desktop.getWindowManager().getWindows();
// Loop over all nodes
for (FXInternalWindow curWindow : windowNodes) {
// Reset Maximized windows to Normal State
if (curWindow.getState().equals(FXInternalWindow.State.MAXIMIZED)) {
curWindow.setState(FXInternalWindow.State.NORMAL);
}
// If needed, set Minimized windows to Normal State
if ((curWindow).getState().equals(FXInternalWindow.State.MINIMIZED) && (IncludeMinimized)) {
(curWindow).setState(FXInternalWindow.State.NORMAL);
}
// Add this window to the "to be resized" list
winndowsToBeResized.add(curWindow);
}
// Rearrange windows if we have a DesktopPane and 1 or more Windows
if (windowNodes.size() > 0) {
int loop = 0;
int newWindowWidth;
int newWindowHeight;
for (FXInternalWindow windowToResize : winndowsToBeResized) {
newWindowWidth = (int) (desktop.getWidth() * CASCADE_PERCENT_WIDTH);
newWindowHeight = (int) (desktop.getHeight() * CASCADE_PERCENT_HEIGHT);
if ((((loop * CASCADE_OFFSET_X) + newWindowWidth) > ((int) desktop.getWidth())) || ((((loop - 1) * CASCADE_OFFSET_Y) + newWindowHeight) > ((int) desktop.getHeight()))) {
loop = 0;
}
windowToResize.resizeRelocate((loop * CASCADE_OFFSET_X), (loop * CASCADE_OFFSET_Y), newWindowWidth, newWindowHeight);
loop++;
}
}
// Set last active window as active
desktop.getWindowManager().windowsProperty().get(desktop.getWindowManager().windowsProperty().getSize() - 1).setActive(true);
}
/**
* Rearrange all FXInternalWindow Windows.
* <p>
* Rearranged windows in either Horizontal Tile, Vertical Tile, or both Horizonal and Vertical layouts.<br>
* <p>
* @param desktop FXDesktopPane pane to be organized
* @param VerHor True for Vertical arrangement, False for Horizontal arrangement
* @param IncludeMinimized Include Minimized windows. Normally only Maximized and Normal State windows are resized.
*/
public static void ArrangeFXIntWinInTileLayout(FXDesktopPane desktop, Boolean VerHor, Boolean IncludeMinimized) {
ObservableList<FXInternalWindow> winndowsToBeResized = FXCollections.observableArrayList();
// Get all Window Nodes from our desktop
ObservableList<Node> windowNodes = desktop.getWindowManager().getPane().getChildren();
// Loop over all nodes
for (Object object : windowNodes) {
// Verify we have a valid FXInternalWindow object
if (object.getClass().equals(FXInternalWindow.class)) {
// Reset Maximized windows to Normal State
if (((FXInternalWindow) object).getState().equals(FXInternalWindow.State.MAXIMIZED)) {
((FXInternalWindow) object).setState(FXInternalWindow.State.NORMAL);
}
// If needed, set Minimized windows to Normal State
if (((FXInternalWindow) object).getState().equals(FXInternalWindow.State.MINIMIZED) && (IncludeMinimized)) {
((FXInternalWindow) object).setState(FXInternalWindow.State.NORMAL);
}
// Add this window to the "to be resized" list
winndowsToBeResized.add(((FXInternalWindow) object));
}
}
// Rearrange windows if we have a DesktopPane and 1 or more Windows
if (windowNodes.size() > 0) {
int[] layoutArray = FXInternalWindowLayout.getBestWindowLayoutArray(winndowsToBeResized.size());
int numCols = 0;
int numRows = 0;
int numRowsLastCol = 0;
int newWindowWidth = 0;
int newWindowHeight = 0;
int newWindowHeightLastCol = 0;
// Single option layout
if ((layoutArray.length == 2)) {
numCols = layoutArray[0];
numRows = layoutArray[1];
newWindowWidth = (int) desktop.getWidth() / numCols;
newWindowHeight = (int) desktop.getHeight() / numRows;
int currentWindowIndex = 0;
for (int colIndex = 0; colIndex < numCols; colIndex++) {
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
winndowsToBeResized.get(currentWindowIndex).resizeRelocate((colIndex * newWindowWidth), (rowIndex * newWindowHeight), newWindowWidth, newWindowHeight);
currentWindowIndex++;
}
}
}
// Single option layout with extra column
if ((layoutArray.length == 4)) {
numCols = layoutArray[0] + layoutArray[2];
numRows = layoutArray[1];
numRowsLastCol = layoutArray[3];
newWindowWidth = (int) desktop.getWidth() / numCols;
newWindowHeight = (int) desktop.getHeight() / numRows;
newWindowHeightLastCol = (int) desktop.getHeight() / numRowsLastCol;
int currentWindowIndex = 0;
for (int colIndex = 0; colIndex < numCols - 1; colIndex++) {
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
winndowsToBeResized.get(currentWindowIndex).resizeRelocate((colIndex * newWindowWidth), (rowIndex * newWindowHeight), newWindowWidth, newWindowHeight);
currentWindowIndex++;
}
}
for (int j = 0; j < numRowsLastCol; j++) {
winndowsToBeResized.get(currentWindowIndex).resizeRelocate(((numCols - 1) * newWindowWidth), (j * newWindowHeightLastCol), newWindowWidth, newWindowHeightLastCol);
currentWindowIndex++;
}
}
// Dual option
if ((layoutArray.length == 6)) {
if (VerHor) {
numCols = layoutArray[0];
numRows = layoutArray[1];
} else {
numCols = layoutArray[4];
numRows = layoutArray[5];
}
newWindowWidth = (int) desktop.getWidth() / numCols;
newWindowHeight = (int) desktop.getHeight() / numRows;
int currentWindowIndex = 0;
for (int colIndex = 0; colIndex < numCols; colIndex++) {
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
winndowsToBeResized.get(currentWindowIndex).resizeRelocate((colIndex * newWindowWidth), (rowIndex * newWindowHeight), newWindowWidth, newWindowHeight);
currentWindowIndex++;
}
}
}
// Dual option with extra column
if ((layoutArray.length == 8)) {
if (VerHor) {
numCols = layoutArray[0] + layoutArray[2];
numRows = layoutArray[1];
numRowsLastCol = layoutArray[3];
} else {
numCols = layoutArray[4] + layoutArray[6];
numRows = layoutArray[5];
numRowsLastCol = layoutArray[7];
}
newWindowWidth = (int) desktop.getWidth() / numCols;
newWindowHeight = (int) desktop.getHeight() / numRows;
newWindowHeightLastCol = (int) desktop.getHeight() / numRowsLastCol;
int currentWindowIndex = 0;
for (int colIndex = 0; colIndex < numCols - 1; colIndex++) {
for (int rowIndex = 0; rowIndex < numRows; rowIndex++) {
winndowsToBeResized.get(currentWindowIndex).resizeRelocate((colIndex * newWindowWidth), (rowIndex * newWindowHeight), newWindowWidth, newWindowHeight);
currentWindowIndex++;
}
}
for (int j = 0; j < numRowsLastCol; j++) {
winndowsToBeResized.get(currentWindowIndex).resizeRelocate(((numCols - 1) * newWindowWidth), (j * newWindowHeightLastCol), newWindowWidth, newWindowHeightLastCol);
currentWindowIndex++;
}
}
}
// Set last active window as active
desktop.getWindowManager().windowsProperty().get(desktop.getWindowManager().windowsProperty().getSize() - 1).setActive(true);
}
/**
* Calculate the best window layout for the number of windows provided.
*
* @param numWin Number of Windows
* @return Either int[2], int[6] or int[8] of columns and rows
*/
public static int[] getBestWindowLayoutArray(int numWin) {
Double sqrtNumWin = Math.sqrt(numWin);
int floorSqrtNumWin = (int) Math.floor(sqrtNumWin);
Double modSqrtNumWinFloorNumWin = sqrtNumWin % floorSqrtNumWin;
Double modNumWinFloorNumWin = numWin % (double) floorSqrtNumWin;
Double numWinDivfloorNumWin = numWin / (double) floorSqrtNumWin;
int x1, y1, x2, y2, x3, y3, x4, y4;
x2 = y2 = x3 = y3 = x4 = y4 = -1;
if (modSqrtNumWinFloorNumWin == 0) {
x1 = sqrtNumWin.intValue();
y1 = floorSqrtNumWin;
} else {
if (modNumWinFloorNumWin == 0) {
x1 = numWinDivfloorNumWin.intValue();
y1 = floorSqrtNumWin;
x2 = -1;
y2 = -1;
x3 = floorSqrtNumWin;
y3 = numWinDivfloorNumWin.intValue();
} else {
if (modSqrtNumWinFloorNumWin < 0.5) {
x1 = floorSqrtNumWin - 1;
y1 = floorSqrtNumWin;
x2 = 1;
y2 = (numWin - ((floorSqrtNumWin - 1) * (floorSqrtNumWin)));
} else {
x1 = floorSqrtNumWin;
y1 = floorSqrtNumWin;
x2 = 1;
y2 = (numWin - (floorSqrtNumWin * floorSqrtNumWin));
x3 = (floorSqrtNumWin - 1);
y3 = (floorSqrtNumWin + 1);
x4 = 1;
y4 = (numWin - ((floorSqrtNumWin - 1) * (floorSqrtNumWin + 1)));
}
}
}
if (x4 != -1) {
int[] A = {x1, y1, x2, y2, x3, y3, x4, y4};
return (A);
} else if (x3 != -1) {
int[] A = {x1, y1, x2, y2, x3, y3};
return (A);
} else if (x2 != -1) {
int[] A = {x1, y1, x2, y2};
return (A);
} else {
int[] A = {x1, y1};
return (A);
}
}
}
Cheers.