diff --git a/Quelea/languages/gb.lang b/Quelea/languages/gb.lang
index 3f5a59ccb..4a7fd59f4 100644
--- a/Quelea/languages/gb.lang
+++ b/Quelea/languages/gb.lang
@@ -716,4 +716,8 @@ filefilters.description.sunday.plus=Sunday plus songs
song.list=Song list
password.empty.label=Empty password found
password.empty.message=The server password cannot be empty. The default password "quelea" will be used unless you enter something in the password box.
+projector.margin.top=Margin Top
+projector.margin.right=Margin Right
+projector.margin.bottom=Margin Bottom
+projector.margin.left=Margin Left
slide.transition.label=Use fade transition between slides
diff --git a/Quelea/src/main/java/org/quelea/services/utils/PercentMargins.java b/Quelea/src/main/java/org/quelea/services/utils/PercentMargins.java
new file mode 100644
index 000000000..e9bef5d68
--- /dev/null
+++ b/Quelea/src/main/java/org/quelea/services/utils/PercentMargins.java
@@ -0,0 +1,77 @@
+/*
+ * This file is part of Quelea, free projection software for churches.
+ *
+ * Copyright (C) 2012 Michael Berry
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.quelea.services.utils;
+
+import javafx.geometry.BoundingBox;
+import javafx.geometry.Bounds;
+
+/**
+ * Percentage-based (0-1) margins to be applied to a display
+ *
+ * @author Dallon Feldner
+ */
+public class PercentMargins {
+
+ private double top;
+ private double right;
+ private double bottom;
+ private double left;
+
+ public PercentMargins(double top, double right, double bottom, double left) {
+ this.top = top;
+ this.right = right;
+ this.bottom = bottom;
+ this.left = left;
+ }
+
+ @Override
+ public String toString() {
+ return top + "," + right + "," + bottom + "," + left;
+ }
+
+ public double getTop() {
+ return top;
+ }
+
+ public double getRight() {
+ return right;
+ }
+
+ public double getBottom() {
+ return bottom;
+ }
+
+ public double getLeft() {
+ return left;
+ }
+
+ public Bounds applyMargins(Bounds coords) {
+ double leftMargin = left * coords.getWidth();
+ double topMargin = top * coords.getHeight();
+
+ return new BoundingBox(
+ coords.getMinX() + leftMargin,
+ coords.getMinY() + topMargin,
+ coords.getWidth() - leftMargin - right* coords.getWidth(),
+ coords.getHeight() - topMargin - bottom* coords.getHeight()
+ );
+ }
+
+}
+
diff --git a/Quelea/src/main/java/org/quelea/services/utils/QueleaProperties.java b/Quelea/src/main/java/org/quelea/services/utils/QueleaProperties.java
index 98ef4190f..7a3b8959a 100644
--- a/Quelea/src/main/java/org/quelea/services/utils/QueleaProperties.java
+++ b/Quelea/src/main/java/org/quelea/services/utils/QueleaProperties.java
@@ -26,6 +26,7 @@
import java.util.Properties;
import java.util.logging.Level;
+import com.sun.istack.NotNull;
import javafx.geometry.BoundingBox;
import javafx.geometry.Bounds;
import javafx.scene.paint.Color;
@@ -1124,6 +1125,10 @@ public Bounds getProjectorCoords() {
Integer.parseInt(prop[3]));
}
+ public Bounds getProjectorCoordsWithMargins() {
+ return applyProjectorMargin(getProjectorCoords());
+ }
+
/**
* Set the custom projector co-ordinates.
*
@@ -2274,6 +2279,57 @@ public double getLyricHeightBounds() {
return Double.parseDouble(getProperty(lyricHeightBoundKey, "0.9"));
}
+ public PercentMargins getProjectorMargin() {
+ String[] parts = getProperty(projectorMarginKey, "0,0,0,0").split(",");
+ if (parts.length == 4) {
+ return new PercentMargins(
+ Double.parseDouble(parts[0]),
+ Double.parseDouble(parts[1]),
+ Double.parseDouble(parts[2]),
+ Double.parseDouble(parts[3])
+ );
+ } else {
+ return new PercentMargins(0,0,0,0);
+ }
+ }
+
+ public void setProjectorMargin(@NotNull PercentMargins margins) {
+ setProperty(projectorMarginKey, margins.toString());
+ }
+
+ public void setProjectorMarginTop(double value) {
+ PercentMargins prop = getProjectorMargin();
+ PercentMargins newProp = new PercentMargins(value, prop.getRight(), prop.getBottom(), prop.getLeft());
+ setProjectorMargin(newProp);
+ }
+
+ public void setProjectorMarginRight(double value) {
+ PercentMargins prop = getProjectorMargin();
+ PercentMargins newProp = new PercentMargins(prop.getTop(), value, prop.getBottom(), prop.getLeft());
+ setProjectorMargin(newProp);
+ }
+
+ public void setProjectorMarginBottom(double value) {
+ PercentMargins prop = getProjectorMargin();
+ PercentMargins newProp = new PercentMargins(prop.getTop(), prop.getRight(), value, prop.getLeft());
+ setProjectorMargin(newProp);
+ }
+
+ public void setProjectorMarginLeft(double value) {
+ PercentMargins prop = getProjectorMargin();
+ PercentMargins newProp = new PercentMargins(prop.getTop(), prop.getRight(), prop.getBottom(), value);
+ setProjectorMargin(newProp);
+ }
+
+ public boolean hasProjectorMargin() {
+ PercentMargins margins = getProjectorMargin();
+ return margins.getTop() > 0 || margins.getLeft() > 0 || margins.getBottom() > 0 || margins.getRight() > 0;
+ }
+
+ public Bounds applyProjectorMargin(Bounds coords) {
+ return getProjectorMargin().applyMargins(coords);
+ }
+
public boolean getDefaultSongDBUpdate() {
return Boolean.parseBoolean(getProperty(defaultSongDbUpdateKey, "true"));
}
diff --git a/Quelea/src/main/java/org/quelea/services/utils/QueleaPropertyKeys.java b/Quelea/src/main/java/org/quelea/services/utils/QueleaPropertyKeys.java
index ecdc11d1d..d014e1911 100644
--- a/Quelea/src/main/java/org/quelea/services/utils/QueleaPropertyKeys.java
+++ b/Quelea/src/main/java/org/quelea/services/utils/QueleaPropertyKeys.java
@@ -126,6 +126,11 @@ public class QueleaPropertyKeys {
public static final String stageWCoordKey = "stage.width.coord";
public static final String stageHCoordKey = "stage.height.coord";
public static final String darkThemeKey = "use.dark.theme";
+ public static final String projectorMarginKey = "projector.margin";
+ public static final String projectorMarginTopKey = "projector.margin.top";
+ public static final String projectorMarginRightKey = "projector.margin.right";
+ public static final String projectorMarginBottomKey = "projector.margin.bottom";
+ public static final String projectorMarginLeftKey = "projector.margin.left";
public static final String useSlideTransitionKey = "use.fade";
public static final String slideTransitionInDurationKey = "slide.transition.duration.in";
public static final String slideTransitionOutDurationKey = "slide.transition.duration.out";
diff --git a/Quelea/src/main/java/org/quelea/windows/main/Main.java b/Quelea/src/main/java/org/quelea/windows/main/Main.java
index dafe8dc84..514abbede 100644
--- a/Quelea/src/main/java/org/quelea/windows/main/Main.java
+++ b/Quelea/src/main/java/org/quelea/windows/main/Main.java
@@ -184,19 +184,31 @@ public void run() {
if (lyricsHidden) {
LOGGER.log(Level.INFO, "Hiding projector display on monitor 0 (base 0!)");
Platform.runLater(() -> {
- fullScreenWindow = new DisplayStage(Utils.getBoundsFromRect2D(monitors.get(0).getVisualBounds()), false);
+ fullScreenWindow = new DisplayStage(
+ QueleaProperties.get().applyProjectorMargin(
+ Utils.getBoundsFromRect2D(monitors.get(0).getVisualBounds())
+ ),
+ false
+ );
fullScreenWindow.hide();
});
} else if (QueleaProperties.get().isProjectorModeCoords()) {
- LOGGER.log(Level.INFO, "Starting projector display: ", QueleaProperties.get().getProjectorCoords());
+ LOGGER.log(Level.INFO, "Starting projector display: ", QueleaProperties.get().getProjectorCoordsWithMargins());
Platform.runLater(() -> {
- fullScreenWindow = new DisplayStage(QueleaProperties.get().getProjectorCoords(), false);
+ fullScreenWindow = new DisplayStage(QueleaProperties.get().getProjectorCoordsWithMargins(), false);
});
} else {
LOGGER.log(Level.INFO, "Starting projector display on monitor {0} (base 0!)", projectorScreen);
Platform.runLater(() -> {
- fullScreenWindow = new DisplayStage(Utils.getBoundsFromRect2D(monitors.get(projectorScreen).getBounds()), false);
- fullScreenWindow.setFullScreenAlwaysOnTop(true);
+ fullScreenWindow = new DisplayStage(
+ QueleaProperties.get().applyProjectorMargin(
+ Utils.getBoundsFromRect2D(monitors.get(projectorScreen).getBounds())
+ ),
+ false
+ );
+ if (!QueleaProperties.get().hasProjectorMargin()) {
+ fullScreenWindow.setFullScreenAlwaysOnTop(true);
+ }
});
}
diff --git a/Quelea/src/main/java/org/quelea/windows/options/DisplayGroup.java b/Quelea/src/main/java/org/quelea/windows/options/DisplayGroup.java
index 5ac7a08b6..284a74796 100644
--- a/Quelea/src/main/java/org/quelea/windows/options/DisplayGroup.java
+++ b/Quelea/src/main/java/org/quelea/windows/options/DisplayGroup.java
@@ -17,6 +17,7 @@
*/
package org.quelea.windows.options;
+import com.dlsc.formsfx.model.structure.DoubleField;
import com.dlsc.formsfx.model.structure.Field;
import com.dlsc.formsfx.model.structure.IntegerField;
import com.dlsc.preferencesfx.formsfx.view.controls.SimpleComboBoxControl;
@@ -24,6 +25,7 @@
import com.dlsc.preferencesfx.model.Group;
import com.dlsc.preferencesfx.model.Setting;
import javafx.beans.property.*;
+import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
@@ -31,8 +33,11 @@
import javafx.geometry.Bounds;
import javafx.stage.Screen;
import org.quelea.services.languages.LabelGrabber;
+import org.quelea.services.utils.PercentMargins;
import org.quelea.services.utils.QueleaProperties;
+import org.quelea.windows.options.customprefs.PercentSliderControl;
+import java.util.ArrayList;
import java.util.HashMap;
import static org.quelea.services.utils.QueleaPropertyKeys.*;
@@ -41,18 +46,20 @@ public class DisplayGroup {
private boolean displayChange = false;
private Group group;
- DisplayGroup(String groupName, boolean custom, HashMap bindings) {
- BooleanProperty useCustomPosition = new SimpleBooleanProperty(false);
- if (groupName.equals(LabelGrabber.INSTANCE.getLabel("projector.screen.label"))) {
- useCustomPosition = new SimpleBooleanProperty(QueleaProperties.get().isProjectorModeCoords());
- } else if (groupName.equals(LabelGrabber.INSTANCE.getLabel("stage.screen.label"))) {
- useCustomPosition = new SimpleBooleanProperty(QueleaProperties.get().isStageModeCoords());
- }
- useCustomPosition.addListener(e -> {
- displayChange = true;
- });
+ DisplayGroup(String groupName, HashMap bindings) {
+
+ boolean isControl = groupName.equals(LabelGrabber.INSTANCE.getLabel(("control.screen.label")));
+ boolean isProjector = groupName.equals(LabelGrabber.INSTANCE.getLabel(("projector.screen.label")));
+ boolean isStage = groupName.equals(LabelGrabber.INSTANCE.getLabel("stage.screen.label"));
- ObservableList availableScreens = getAvailableScreens(custom);
+ // can be disabled?
+ boolean noScreen = isProjector || isStage;
+ // Support a custom position?
+ boolean useCustom = isProjector || isStage;
+ // Support display margins?
+ boolean useMargins = isProjector;
+
+ ObservableList availableScreens = getAvailableScreens(useCustom);
ListProperty screenListProperty = new SimpleListProperty<>(availableScreens);
ObjectProperty screenSelectProperty = new SimpleObjectProperty<>(availableScreens.get(0));
Field customControl = Field.ofSingleSelectionType(screenListProperty, screenSelectProperty).render(
@@ -66,80 +73,188 @@ public class DisplayGroup {
displayChange = true;
});
- if (!custom) {
- int screen = QueleaProperties.get().getControlScreen();
+ ArrayList settings = new ArrayList<>();
+
+ int screen;
+ String screenKey;
+ if (isControl)
+ {
+ screen = QueleaProperties.get().getControlScreen();
+ screenKey = controlScreenKey;
+ } else if (isProjector) {
+ screen = QueleaProperties.get().getProjectorScreen();
+ screenKey = projectorScreenKey;
+ } else if (isStage) {
+ screen = QueleaProperties.get().getStageScreen();
+ screenKey = stageScreenKey;
+ } else {
+ throw new IllegalArgumentException("Unsupported groupName: " + groupName);
+ }
+
+ if (noScreen) {
+ screen++; // Compensate for "none" value in available screens
+ screenSelectProperty.setValue(screen > 0 && screen < availableScreens.size() ? availableScreens.get(screen) : availableScreens.get(0));
+ } else {
screenSelectProperty.setValue(screen > -1 ? availableScreens.get(screen) : availableScreens.get(0));
- group = Group.of(groupName,
- Setting.of(groupName, customControl, screenSelectProperty).customKey(controlScreenKey)
- );
+ }
+
+ settings.add(Setting.of(groupName, customControl, screenSelectProperty).customKey(screenKey));
+
+ if (useCustom) {
+ setupCustomPosition(bindings, isProjector, isStage, customControl, settings);
+ }
+
+ if (useMargins) {
+ setupMargins(isProjector, settings);
+ }
+
+
+ Setting[] settingsArray = new Setting[settings.size()];
+ group = Group.of(groupName,
+ settings.toArray(settingsArray)
+ );
+ }
+
+ private void setupCustomPosition( HashMap bindings, boolean isProjector, boolean isStage, Field customControl, ArrayList settings) {
+ Bounds bounds;
+ BooleanProperty useCustomPosition;
+ if (isProjector) {
+ bounds = QueleaProperties.get().getProjectorCoords();
+ useCustomPosition = new SimpleBooleanProperty(QueleaProperties.get().isProjectorModeCoords());
+ } else if (isStage) {
+ bounds = QueleaProperties.get().getStageCoords();
+ useCustomPosition = new SimpleBooleanProperty(QueleaProperties.get().isStageModeCoords());
} else {
- int screen;
- Bounds bounds;
- if (groupName.equals(LabelGrabber.INSTANCE.getLabel("projector.screen.label"))) {
- screen = QueleaProperties.get().getProjectorScreen();
- bounds = QueleaProperties.get().getProjectorCoords();
+ throw new IllegalArgumentException("Unsupported groupName - is neither projector nor stage");
+ }
+
+
+ IntegerProperty widthProperty = new SimpleIntegerProperty((int) bounds.getWidth());
+ IntegerProperty heightProperty = new SimpleIntegerProperty((int) bounds.getHeight());
+ IntegerProperty xProperty = new SimpleIntegerProperty((int) bounds.getMinX());
+ IntegerProperty yProperty = new SimpleIntegerProperty((int) bounds.getMinY());
+ IntegerField sizeWith = Field.ofIntegerType(widthProperty).render(
+ new SimpleIntegerControl());
+ IntegerField sizeHeight = Field.ofIntegerType(heightProperty).render(
+ new SimpleIntegerControl());
+ IntegerField posX = Field.ofIntegerType(xProperty).render(
+ new SimpleIntegerControl());
+ IntegerField posY = Field.ofIntegerType(yProperty).render(
+ new SimpleIntegerControl());
+
+ widthProperty.addListener(e -> {
+ displayChange = true;
+ });
+
+ heightProperty.addListener(e -> {
+ displayChange = true;
+ });
+
+ xProperty.addListener(e -> {
+ displayChange = true;
+ });
+
+ yProperty.addListener(e -> {
+ displayChange = true;
+ });
+
+ useCustomPosition.addListener(e -> {
+ displayChange = true;
+ });
+
+
+ settings.add(Setting.of(LabelGrabber.INSTANCE.getLabel("custom.position.text"), useCustomPosition)
+ .customKey(isProjector ? projectorModeKey : stageModeKey));
+ settings.add(Setting.of("W", sizeWith, widthProperty)
+ .customKey(isProjector ? projectorWCoordKey : stageWCoordKey));
+ settings.add(Setting.of("H", sizeHeight, heightProperty)
+ .customKey(isProjector ? projectorHCoordKey : stageHCoordKey));
+ settings.add(Setting.of("X", posX, xProperty)
+ .customKey(isProjector ? projectorXCoordKey : stageXCoordKey));
+ settings.add(Setting.of("Y", posY, yProperty)
+ .customKey(isProjector ? projectorYCoordKey : stageYCoordKey));
+
+ bindings.put(sizeWith, useCustomPosition.not());
+ bindings.put(sizeHeight, useCustomPosition.not());
+ bindings.put(posX, useCustomPosition.not());
+ bindings.put(posY, useCustomPosition.not());
+ bindings.put(customControl, useCustomPosition);
+ }
+
+ private void setupMargins(boolean isProjector, ArrayList settings) {
+ PercentMargins margins;
+ if (isProjector) {
+ margins = QueleaProperties.get().getProjectorMargin();
+ } else {
+ throw new IllegalArgumentException("Unsupported groupName (isn't projector)");
+ }
+
+ DoubleProperty marginTopProperty = new SimpleDoubleProperty(margins.getTop());
+ DoubleProperty marginRightProperty = new SimpleDoubleProperty(margins.getRight());
+ DoubleProperty marginBottomProperty = new SimpleDoubleProperty(margins.getBottom());
+ DoubleProperty marginLeftProperty = new SimpleDoubleProperty(margins.getLeft());
+
+ DoubleField marginTopField = Field.ofDoubleType(marginTopProperty).render(
+ new PercentSliderControl(0.0, 0.99, 2));
+ DoubleField marginRightField = Field.ofDoubleType(marginRightProperty).render(
+ new PercentSliderControl(0.0, 0.99, 2));
+ DoubleField marginBottomField = Field.ofDoubleType(marginBottomProperty).render(
+ new PercentSliderControl(0.0, 0.99, 2));
+ DoubleField marginLeftField = Field.ofDoubleType(marginLeftProperty).render(
+ new PercentSliderControl(0.0, 0.99, 2));
+
+ ChangeListener onMarginNumberChange = (observable, oldValue, newValue) -> {
+ DoubleProperty property;
+ DoubleProperty opposite;
+ if (observable == marginTopProperty) {
+ property = marginTopProperty;
+ opposite = marginBottomProperty;
+ } else if (observable == marginRightProperty) {
+ property = marginRightProperty;
+ opposite = marginLeftProperty;
+ } else if (observable == marginBottomProperty) {
+ property = marginBottomProperty;
+ opposite = marginTopProperty;
+ } else if (observable == marginLeftProperty) {
+ property = marginLeftProperty;
+ opposite = marginRightProperty;
} else {
- screen = QueleaProperties.get().getStageScreen();
- bounds = QueleaProperties.get().getStageCoords();
+ throw new IllegalArgumentException();
+ }
+
+ displayChange = true;
+
+ // make sure the margins only add up to 99 at most, leaving 1% for content
+ double total = property.getValue() + opposite.getValue();
+ if (total > 0.99) {
+ double suggestedOpposite = 0.99 - property.getValue();
+ if (suggestedOpposite > 0) {
+ opposite.set(suggestedOpposite);
+ } else {
+ // A number greater than 99 has been selected
+ // clamp to 99
+ property.set(0.99);
+ opposite.set(0);
+ }
}
+ };
- IntegerProperty widthProperty = new SimpleIntegerProperty((int) bounds.getWidth());
- IntegerProperty heightProperty = new SimpleIntegerProperty((int) bounds.getHeight());
- IntegerProperty xProperty = new SimpleIntegerProperty((int) bounds.getMinX());
- IntegerProperty yProperty = new SimpleIntegerProperty((int) bounds.getMinY());
- IntegerField sizeWith = Field.ofIntegerType(widthProperty).render(
- new SimpleIntegerControl());
- IntegerField sizeHeight = Field.ofIntegerType(heightProperty).render(
- new SimpleIntegerControl());
- IntegerField posX = Field.ofIntegerType(xProperty).render(
- new SimpleIntegerControl());
- IntegerField posY = Field.ofIntegerType(yProperty).render(
- new SimpleIntegerControl());
-
- widthProperty.addListener(e -> {
- displayChange = true;
- });
-
- heightProperty.addListener(e -> {
- displayChange = true;
- });
-
- xProperty.addListener(e -> {
- displayChange = true;
- });
-
- yProperty.addListener(e -> {
- displayChange = true;
- });
- screen++; // Compensate for "none" value in available screens
+ marginTopProperty.addListener(onMarginNumberChange);
+ marginRightProperty.addListener(onMarginNumberChange);
+ marginBottomProperty.addListener(onMarginNumberChange);
+ marginLeftProperty.addListener(onMarginNumberChange);
- screenSelectProperty.setValue(screen > 0 && screen < availableScreens.size() ? availableScreens.get(screen) : availableScreens.get(0));
- boolean projectorGroup = groupName.equals(LabelGrabber.INSTANCE.getLabel("projector.screen.label"));
-
- group = Group.of(groupName,
- Setting.of(groupName, customControl, screenSelectProperty)
- .customKey(projectorGroup ? projectorScreenKey : stageScreenKey),
- Setting.of(LabelGrabber.INSTANCE.getLabel("custom.position.text"), useCustomPosition)
- .customKey(projectorGroup ? projectorModeKey : stageModeKey),
- Setting.of("W", sizeWith, widthProperty)
- .customKey(projectorGroup ? projectorWCoordKey : stageWCoordKey),
- Setting.of("H", sizeHeight, heightProperty)
- .customKey(projectorGroup ? projectorHCoordKey : stageHCoordKey),
- Setting.of("X", posX, xProperty)
- .customKey(projectorGroup ? projectorXCoordKey : stageXCoordKey),
- Setting.of("Y", posY, yProperty)
- .customKey(projectorGroup ? projectorYCoordKey : stageYCoordKey)
- );
-
- bindings.put(sizeWith, useCustomPosition.not());
- bindings.put(sizeHeight, useCustomPosition.not());
- bindings.put(posX, useCustomPosition.not());
- bindings.put(posY, useCustomPosition.not());
- bindings.put(customControl, useCustomPosition);
- }
- }
+ settings.add(Setting.of(LabelGrabber.INSTANCE.getLabel("projector.margin.top"), marginTopField, marginTopProperty)
+ .customKey(projectorMarginTopKey));
+ settings.add(Setting.of(LabelGrabber.INSTANCE.getLabel("projector.margin.right"), marginRightField, marginRightProperty)
+ .customKey(projectorMarginRightKey));
+ settings.add(Setting.of(LabelGrabber.INSTANCE.getLabel("projector.margin.bottom"), marginBottomField, marginBottomProperty)
+ .customKey(projectorMarginBottomKey));
+ settings.add(Setting.of(LabelGrabber.INSTANCE.getLabel("projector.margin.left"), marginLeftField, marginLeftProperty)
+ .customKey(projectorMarginLeftKey));
+ }
/**
* Get a list model describing the available graphical devices.
diff --git a/Quelea/src/main/java/org/quelea/windows/options/OptionsDisplaySetupPanel.java b/Quelea/src/main/java/org/quelea/windows/options/OptionsDisplaySetupPanel.java
index 1d108e4ca..a54ed15cc 100644
--- a/Quelea/src/main/java/org/quelea/windows/options/OptionsDisplaySetupPanel.java
+++ b/Quelea/src/main/java/org/quelea/windows/options/OptionsDisplaySetupPanel.java
@@ -46,9 +46,9 @@ public class OptionsDisplaySetupPanel {
*/
OptionsDisplaySetupPanel(HashMap bindings) {
this.bindings = bindings;
- controlScreen = new DisplayGroup(LabelGrabber.INSTANCE.getLabel("control.screen.label"), false, bindings);
- projectorScreen = new DisplayGroup(LabelGrabber.INSTANCE.getLabel("projector.screen.label"), true, bindings);
- stageScreen = new DisplayGroup(LabelGrabber.INSTANCE.getLabel("stage.screen.label"), true, bindings);
+ controlScreen = new DisplayGroup(LabelGrabber.INSTANCE.getLabel("control.screen.label"), bindings);
+ projectorScreen = new DisplayGroup(LabelGrabber.INSTANCE.getLabel("projector.screen.label"), bindings);
+ stageScreen = new DisplayGroup(LabelGrabber.INSTANCE.getLabel("stage.screen.label"), bindings);
GraphicsDeviceWatcher.INSTANCE.addGraphicsDeviceListener(devices -> {
QueleaApp.get().getMainWindow().getPreferencesDialog().updatePos();
diff --git a/Quelea/src/main/java/org/quelea/windows/options/PreferenceStorageHandler.java b/Quelea/src/main/java/org/quelea/windows/options/PreferenceStorageHandler.java
index aa18aea16..a654058b3 100644
--- a/Quelea/src/main/java/org/quelea/windows/options/PreferenceStorageHandler.java
+++ b/Quelea/src/main/java/org/quelea/windows/options/PreferenceStorageHandler.java
@@ -208,6 +208,18 @@ public void saveObject(String breadcrumb, Object object) {
case QueleaPropertyKeys.projectorYCoordKey:
QueleaProperties.get().setYProjectorCoord(object.toString());
break;
+ case QueleaPropertyKeys.projectorMarginTopKey:
+ QueleaProperties.get().setProjectorMarginTop((Double) object);
+ break;
+ case QueleaPropertyKeys.projectorMarginRightKey:
+ QueleaProperties.get().setProjectorMarginRight((Double) object);
+ break;
+ case QueleaPropertyKeys.projectorMarginBottomKey:
+ QueleaProperties.get().setProjectorMarginBottom((Double) object);
+ break;
+ case QueleaPropertyKeys.projectorMarginLeftKey:
+ QueleaProperties.get().setProjectorMarginLeft((Double) object);
+ break;
case QueleaPropertyKeys.stageHCoordKey:
QueleaProperties.get().setHeightStageCoord(object.toString());
break;
@@ -336,6 +348,14 @@ public Object loadObject(String breadcrumb, Object defaultObject) {
return QueleaProperties.get().getProjectorCoords().getMinX();
case QueleaPropertyKeys.projectorYCoordKey:
return QueleaProperties.get().getProjectorCoords().getMinY();
+ case QueleaPropertyKeys.projectorMarginTopKey:
+ return QueleaProperties.get().getProjectorMargin().getTop();
+ case QueleaPropertyKeys.projectorMarginRightKey:
+ return QueleaProperties.get().getProjectorMargin().getRight();
+ case QueleaPropertyKeys.projectorMarginBottomKey:
+ return QueleaProperties.get().getProjectorMargin().getBottom();
+ case QueleaPropertyKeys.projectorMarginLeftKey:
+ return QueleaProperties.get().getProjectorMargin().getLeft();
case QueleaPropertyKeys.stageHCoordKey:
return QueleaProperties.get().getStageCoords().getHeight();
case QueleaPropertyKeys.stageWCoordKey:
diff --git a/Quelea/src/main/java/org/quelea/windows/options/PreferencesDialog.java b/Quelea/src/main/java/org/quelea/windows/options/PreferencesDialog.java
index 33ac4fe72..550ede78d 100644
--- a/Quelea/src/main/java/org/quelea/windows/options/PreferencesDialog.java
+++ b/Quelea/src/main/java/org/quelea/windows/options/PreferencesDialog.java
@@ -169,11 +169,15 @@ public void updatePos() {
int projectorScreen = QueleaProperties.get().getProjectorScreen();
Bounds bounds;
if (QueleaProperties.get().isProjectorModeCoords()) {
- bounds = QueleaProperties.get().getProjectorCoords();
+ bounds = QueleaProperties.get().getProjectorCoordsWithMargins();
} else {
- bounds = Utils.getBoundsFromRect2D(
- monitors.get(projectorScreen < 0 || projectorScreen >= monitors.size() ? 0 : projectorScreen)
- .getBounds());
+ bounds = QueleaProperties.get().applyProjectorMargin(
+ Utils.getBoundsFromRect2D(
+ monitors
+ .get(projectorScreen < 0 || projectorScreen >= monitors.size() ? 0 : projectorScreen)
+ .getBounds()
+ )
+ );
}
fiLyricWindow.setAreaImmediate(bounds);
if (!QueleaApp.get().getMainWindow().getMainPanel().getLivePanel().getHide().isSelected()) {
@@ -186,7 +190,9 @@ public void updatePos() {
fiLyricWindow.hide();
VLCWindow.INSTANCE.refreshPosition();
} else {
- fiLyricWindow.setFullScreenAlwaysOnTop(true);
+ if (!QueleaProperties.get().hasProjectorMargin()) {
+ fiLyricWindow.setFullScreenAlwaysOnTop(true);
+ }
}
} else {
fiLyricWindow.setFullScreenAlwaysOnTop(false);