mirror of
https://github.com/maxkratz/lectureStudio.git
synced 2024-05-18 20:00:16 +00:00
Merge PDFPC features (#878)
* added commandline support to open documents (#802) * added commandline support to open documents * fixes to show Error PopUp * Feature/overlay (#803) * overlay prototype * changed color removed sysout * removed popup * Bugfix for single line slides readability improved * Feature/notes (#843) * added split for right notes * set default slide position to UNKNOWN * added menu to switch modes * added left notes * added new Tab and external window for note slide * minor refactoring correct menu selection * center slideNotesView * render left side correct * removed workaround and output * fix merge imports --------- Co-authored-by: Alex Andres <58339654+devopvoid@users.noreply.github.com> * Fixed merge conflict with slide notes feature * Feature/bookmarks (#842) * added toolbar actions for bookmark navigation * improved toolbar actions for bookmark navigation * typo fix * added icons and remove bookmark toolbar button * handle delete for not bookmarked pages * reverted buttons in preview minor fixes * added bookmark removed info to menu * fix menuitem for nextBookmark * fixed errorHandling and added unittests --------- Co-authored-by: Dustin Ringel <Dustin.Ringel@student.hs-rm.de> Co-authored-by: Alex Andres <58339654+devopvoid@users.noreply.github.com> * Fixed merge conflict with the bookmarks feature * Fixed action GC in ExternalFrame #777 * Fixed 'view' menu translations and item order #778 * Fixed goto bookmark * Show notes slide above the thumbnails * Fixed note slide positioning * Fixed updating canvas bounds for the StylusListener * Refactored view position handling * Move note slide with the slide preview * Move peer view with the slide preview * Refactored split notes handling * Improved determining the note slide * Document: do not set note slide position if there are no note slides * Do not show note slides when the document has none * Merged key bindings * Merged goto slide number * Fixed NotificationPopup size and position * Minor split-view fix in the slide-view * Fixed view component movement in SwingSlidesView * Fixed MainPresenterTest * Minor translation fixes * Fixed slide preview docking * Fixed external frame switching * Fixed external frame switching for note slide and slide preview * Fixed external note slide frame closing --------- Co-authored-by: krueml0815 <66517311+krueml0815@users.noreply.github.com> Co-authored-by: Dustin Ringel <Dustin.Ringel@student.hs-rm.de>
This commit is contained in:
parent
d7059fbfe9
commit
fea24d42ca
|
@ -108,9 +108,7 @@ public abstract class ApplicationBase implements Application {
|
|||
|
||||
File file = new File(utf8Path);
|
||||
|
||||
if (file.exists()) {
|
||||
OPEN_FILES.add(file);
|
||||
}
|
||||
OPEN_FILES.add(file);
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
@ -107,6 +107,7 @@ public abstract class ApplicationContext {
|
|||
ppProvider.put(ViewType.User, new PresentationParameterProvider(config));
|
||||
ppProvider.put(ViewType.Preview, new PresentationParameterProvider(config));
|
||||
ppProvider.put(ViewType.Presentation, new PresentationParameterProvider(config));
|
||||
ppProvider.put(ViewType.Slide_Notes, new PresentationParameterProvider(config));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.lecturestudio.core.bus.event;
|
||||
|
||||
import org.lecturestudio.core.model.Page;
|
||||
|
||||
public class BookmarkEvent extends BusEvent {
|
||||
|
||||
/** Enum with the {@link BookmarkEvent} types. */
|
||||
public enum Type { CREATED, REMOVED};
|
||||
|
||||
/** the {@link Type} of the {@link BookmarkEvent}. */
|
||||
private final Type type;
|
||||
|
||||
private final Page page;
|
||||
|
||||
/**
|
||||
* Create the {@link BookmarkEvent} with specified page and type.
|
||||
*
|
||||
* @param page The page.
|
||||
* @param type The type of the {@link BookmarkEvent}.
|
||||
*/
|
||||
public BookmarkEvent(Page page, BookmarkEvent.Type type) {
|
||||
this.page = page;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of the {@link BookmarkEvent}.
|
||||
*
|
||||
* @return The type of the {@link BookmarkEvent}.
|
||||
*/
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the page.
|
||||
*
|
||||
* @return The page.
|
||||
*/
|
||||
|
||||
public Page getPage() {
|
||||
return page;
|
||||
}
|
||||
/**
|
||||
* Indicates whether the {@link BookmarkEvent} is created.
|
||||
*
|
||||
* @return {@code true} if the {@link #type} equals {@code Type.CREATED}, otherwise {@code false}.
|
||||
*/
|
||||
public boolean isCreated() {
|
||||
return type == Type.CREATED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the {@link BookmarkEvent} is removed.
|
||||
*
|
||||
* @return {@code true} if the {@link #type} equals {@code Type.REMOVED}, otherwise {@code false}.
|
||||
*/
|
||||
public boolean isRemoved() {
|
||||
return type == Type.REMOVED;
|
||||
}
|
||||
|
||||
}
|
|
@ -109,7 +109,12 @@ public class RenderController extends Controller {
|
|||
final PresentationParameterProvider ppProvider = getContext().getPagePropertyProvider(viewType);
|
||||
final PresentationParameter parameter = ppProvider.getParameter(page);
|
||||
|
||||
page.getDocument().getDocumentRenderer().render(page, parameter, image);
|
||||
if (viewType == ViewType.Slide_Notes){
|
||||
page.getDocument().getDocumentRenderer().renderNotes(page, parameter, image);
|
||||
}
|
||||
else {
|
||||
page.getDocument().getDocumentRenderer().render(page, parameter, image);
|
||||
}
|
||||
|
||||
if (page.getDocument().isWhiteboard()) {
|
||||
renderGrid(image, parameter, viewType);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.lecturestudio.core.model;
|
||||
|
||||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -27,6 +28,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.lecturestudio.core.geometry.Dimension2D;
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
|
@ -92,6 +94,11 @@ public class Document {
|
|||
/** The unique ID of this document. */
|
||||
private UUID uid;
|
||||
|
||||
/** Position of notes */
|
||||
private NotesPosition splitSlideNotesPosition = NotesPosition.UNKNOWN;
|
||||
|
||||
/** Position of Notes in new Documents for export. Setting the splitSlideNotesPosition variable ends in broken PDF. */
|
||||
private NotesPosition actualSplitSlideNotesPosition = NotesPosition.UNKNOWN;
|
||||
|
||||
/**
|
||||
* Create a new {@link Document}.
|
||||
|
@ -255,7 +262,7 @@ public class Document {
|
|||
* @return The media box of the specified page.
|
||||
*/
|
||||
public Rectangle2D getPageRect(int pageIndex) {
|
||||
return pdfDocument.getPageMediaBox(pageIndex);
|
||||
return pdfDocument.getPageMediaBox(pageIndex, splitSlideNotesPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -277,7 +284,7 @@ public class Document {
|
|||
* @return A list of the text positions.
|
||||
*/
|
||||
public List<Rectangle2D> getTextPositions(int pageIndex) {
|
||||
return pdfDocument.getNormalizedWordPositions(pageIndex);
|
||||
return pdfDocument.getNormalizedWordPositions(pageIndex, splitSlideNotesPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -493,6 +500,17 @@ public class Document {
|
|||
return importPage(page, pageRect);
|
||||
}
|
||||
|
||||
public boolean hasNoteSlide() {
|
||||
Page p = getPage(0);
|
||||
if (isNull(p)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Rectangle2D bounds = pdfDocument.getPageBounds(0);
|
||||
|
||||
return bounds.getWidth() / bounds.getHeight() >= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of the document.
|
||||
*
|
||||
|
@ -719,12 +737,28 @@ public class Document {
|
|||
setDocumentType(DocumentType.PDF);
|
||||
|
||||
loadPages();
|
||||
loadNoteSlidePosition();
|
||||
}
|
||||
|
||||
private void loadNoteSlidePosition() {
|
||||
if (getSplitSlideNotesPosition() == NotesPosition.UNKNOWN) {
|
||||
if (hasNoteSlide()) {
|
||||
setSplitSlideNotesPosition(NotesPosition.RIGHT);
|
||||
}
|
||||
else {
|
||||
setSplitSlideNotesPosition(NotesPosition.NONE);
|
||||
}
|
||||
|
||||
calculateCropBox();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadPages() {
|
||||
pages.clear();
|
||||
|
||||
int pageCount = pdfDocument.getPageCount();
|
||||
String[] prevSplitPageText = new String[2];
|
||||
String[] splitPageText;
|
||||
|
||||
for (int number = 0; number < pageCount; number++) {
|
||||
Page page = new Page(this, number);
|
||||
|
@ -737,6 +771,26 @@ public class Document {
|
|||
}
|
||||
}
|
||||
|
||||
splitPageText = page.getPageText().split("\n");
|
||||
|
||||
if (splitPageText.length >= 2 && prevSplitPageText.length >= 2 &&
|
||||
Stream.of(prevSplitPageText[0], prevSplitPageText[1], splitPageText[0], splitPageText[1])
|
||||
.allMatch(Objects::nonNull)) {
|
||||
if (prevSplitPageText[0].equals(splitPageText[0]) && prevSplitPageText[1].equals(splitPageText[1])) {
|
||||
page.setOverlay(true);
|
||||
|
||||
if (number > 0) {
|
||||
Page prevPage = pages.get(number - 1);
|
||||
prevPage.setOverlay(true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
prevSplitPageText = splitPageText;
|
||||
}
|
||||
}
|
||||
else {
|
||||
prevSplitPageText = splitPageText;
|
||||
}
|
||||
pages.add(page);
|
||||
}
|
||||
|
||||
|
@ -745,4 +799,62 @@ public class Document {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the crop-box for all pages, depending on splitSlideNotesPosition variable.
|
||||
*/
|
||||
public void calculateCropBox() {
|
||||
int width;
|
||||
int height;
|
||||
|
||||
if (splitSlideNotesPosition == NotesPosition.LEFT) {
|
||||
for (int i = 0; i < getPageCount(); i++) {
|
||||
width = (int) getPageRect(i).getWidth();
|
||||
height = (int) getPageRect(i).getHeight();
|
||||
pdfDocument.setCropbox(i, width, 0, width, height);
|
||||
}
|
||||
}
|
||||
else if (splitSlideNotesPosition == NotesPosition.RIGHT || splitSlideNotesPosition == NotesPosition.NONE) {
|
||||
for (int i = 0; i < getPageCount(); i++) {
|
||||
width = (int) getPageRect(i).getWidth();
|
||||
height = (int) getPageRect(i).getHeight();
|
||||
pdfDocument.setCropbox(i, 0, 0, width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the notes when the slide needs to be split
|
||||
*
|
||||
* @return position of the notes on the slide
|
||||
*/
|
||||
public NotesPosition getSplitSlideNotesPosition() {
|
||||
return splitSlideNotesPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the slide notes
|
||||
*
|
||||
* @param position a position that doesn't depend on prediction
|
||||
*/
|
||||
public void setSplitSlideNotesPosition(NotesPosition position) {
|
||||
this.splitSlideNotesPosition = position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the notes when the slide needs to be split on exports
|
||||
*
|
||||
* @return position of the notes on the slide
|
||||
*/
|
||||
public NotesPosition getActualSplitSlideNotesPosition() {
|
||||
return actualSplitSlideNotesPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the slide notes for PDF exports
|
||||
*
|
||||
* @param position a position that doesn't depend on prediction
|
||||
*/
|
||||
public void setActualSplitSlideNotesPosition(NotesPosition position) {
|
||||
this.actualSplitSlideNotesPosition = position;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
*
|
||||
* * Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* * Embedded Systems and Applications Group.
|
||||
* *
|
||||
* * 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.lecturestudio.core.model;
|
||||
|
||||
public enum NotesPosition {
|
||||
|
||||
LEFT,
|
||||
RIGHT,
|
||||
NONE,
|
||||
UNKNOWN
|
||||
|
||||
}
|
|
@ -95,6 +95,8 @@ public class Page {
|
|||
/** The unique ID of this document. */
|
||||
private UUID uid;
|
||||
|
||||
private boolean overlay = false;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Page with the specified document and page number.
|
||||
|
@ -659,4 +661,11 @@ public class Page {
|
|||
return annotationsAsString;
|
||||
}
|
||||
|
||||
public boolean isOverlay() {
|
||||
return overlay;
|
||||
}
|
||||
|
||||
public void setOverlay(boolean overlay) {
|
||||
this.overlay = overlay;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public class ScreenDocument extends Document {
|
|||
|
||||
int padding = (int) (PADDING * s);
|
||||
|
||||
PDFGraphics2D g2d = (PDFGraphics2D) getPdfDocument().createAppendablePageGraphics2D(pageIndex);
|
||||
PDFGraphics2D g2d = (PDFGraphics2D) getPdfDocument().createAppendablePageGraphics2D(pageIndex, getSplitSlideNotesPosition());
|
||||
// Draw screen frame with a border around it.
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.drawRect(x - padding, y - padding, w + padding * 2, h + padding * 2);
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.Set;
|
|||
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.model.DocumentOutline;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.shape.Shape;
|
||||
|
||||
public interface DocumentAdapter {
|
||||
|
@ -63,6 +64,18 @@ public interface DocumentAdapter {
|
|||
*/
|
||||
Graphics2D createGraphics(int pageIndex, String name, boolean appendContent);
|
||||
|
||||
/**
|
||||
* Create a {@link Graphics2D} object with the specified parameters.
|
||||
*
|
||||
* @param pageIndex The index of the PDF page to which to draw.
|
||||
* @param name The PDF graphics stream name.
|
||||
* @param appendContent {@code true} if content should be appended to the existing one, {@code false} to overwrite.
|
||||
* @param notesPosition The position of split slides notes
|
||||
*
|
||||
* @return The newly created {@link Graphics2D} object.
|
||||
*/
|
||||
Graphics2D createGraphics(int pageIndex, String name, boolean appendContent, NotesPosition notesPosition);
|
||||
|
||||
/**
|
||||
* Set the title of the document.
|
||||
*
|
||||
|
@ -95,10 +108,11 @@ public interface DocumentAdapter {
|
|||
* Get the bounds of the page that has the specified page number.
|
||||
*
|
||||
* @param pageNumber The page number.
|
||||
* @param position The position of notes on a page.
|
||||
*
|
||||
* @return The bounds of the page that has the specified page number.
|
||||
*/
|
||||
Rectangle2D getPageBounds(int pageNumber);
|
||||
Rectangle2D getPageBounds(int pageNumber, NotesPosition position);
|
||||
|
||||
/**
|
||||
* Get the number of pages in the document.
|
||||
|
@ -120,10 +134,11 @@ public interface DocumentAdapter {
|
|||
* Get the word bounds of the page that has the specified page number.
|
||||
*
|
||||
* @param pageNumber The page number.
|
||||
* @param splitNotesPosition Position of the slide notes
|
||||
*
|
||||
* @return The word bounds of the page that has the specified page number.
|
||||
*/
|
||||
List<Rectangle2D> getPageWordsNormalized(int pageNumber) throws IOException;
|
||||
List<Rectangle2D> getPageWordsNormalized(int pageNumber, NotesPosition splitNotesPosition) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the text bounds of the page that has the specified page number.
|
||||
|
|
|
@ -28,4 +28,6 @@ public interface DocumentRenderer {
|
|||
|
||||
void render(Page page, PresentationParameter parameter, BufferedImage image) throws IOException;
|
||||
|
||||
void renderNotes(Page page, PresentationParameter parameter, BufferedImage image) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||
import org.lecturestudio.core.geometry.Dimension2D;
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.model.DocumentOutline;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.shape.Shape;
|
||||
import org.lecturestudio.core.pdf.mupdf.MuPDFDocument;
|
||||
import org.lecturestudio.core.pdf.pdfbox.PDFBoxDocument;
|
||||
|
@ -156,6 +157,29 @@ public class PdfDocument {
|
|||
muPDFDocument.deletePage(pageNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bounds of the page that has the specified page index.
|
||||
*
|
||||
* @param pageIndex The page index.
|
||||
* @param position The position of notes on a page.
|
||||
*
|
||||
* @return The bounds of the page that has the specified page index.
|
||||
*/
|
||||
public Rectangle2D getPageMediaBox(int pageIndex, NotesPosition position) {
|
||||
return pdfBoxDocument.getPageBounds(pageIndex, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bounds of the page that has the specified page index.
|
||||
*
|
||||
* @param pageIndex The page index.
|
||||
*
|
||||
* @return The bounds of the page that has the specified page index.
|
||||
*/
|
||||
public Rectangle2D getPageBounds(int pageIndex) {
|
||||
return muPDFDocument.getPageBounds(pageIndex, NotesPosition.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bounds of the page that has the specified page index.
|
||||
*
|
||||
|
@ -164,7 +188,7 @@ public class PdfDocument {
|
|||
* @return The bounds of the page that has the specified page index.
|
||||
*/
|
||||
public Rectangle2D getPageMediaBox(int pageIndex) {
|
||||
return pdfBoxDocument.getPageBounds(pageIndex);
|
||||
return getPageMediaBox(pageIndex, NotesPosition.UNKNOWN);
|
||||
}
|
||||
|
||||
public void setPageContentTransform(int pageIndex, AffineTransform transform) throws IOException {
|
||||
|
@ -177,6 +201,9 @@ public class PdfDocument {
|
|||
return pdfBoxDocument.importPage(pdfDocument.pdfBoxDocument, pageIndex, pageRect);
|
||||
}
|
||||
|
||||
public void setCropbox(int pageNumber,int x, int y, int width, int height){
|
||||
pdfBoxDocument.setCropbox(pageNumber,x , y, width,height);
|
||||
}
|
||||
/**
|
||||
* Replaces the page that has the {@code pageIndex} with the page
|
||||
* that has {@code docIndex} in {@code newPdfDocument}.
|
||||
|
@ -212,11 +239,12 @@ public class PdfDocument {
|
|||
* The content will be appended to the existing one.
|
||||
*
|
||||
* @param pageIndex The index of the page to which to draw.
|
||||
* @param notesPosition The position of split slides notes
|
||||
*
|
||||
* @return The newly created {@link Graphics2D} object.
|
||||
*/
|
||||
public Graphics2D createAppendablePageGraphics2D(int pageIndex) {
|
||||
return pdfBoxDocument.createGraphics(pageIndex, null, true);
|
||||
public Graphics2D createAppendablePageGraphics2D(int pageIndex, NotesPosition notesPosition) {
|
||||
return pdfBoxDocument.createGraphics(pageIndex, null, true, notesPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,11 +253,12 @@ public class PdfDocument {
|
|||
*
|
||||
* @param pageIndex The index of the page to which to draw.
|
||||
* @param name The PDF graphics stream name.
|
||||
*
|
||||
* @param notesPosition The position of split slides notes
|
||||
|
||||
* @return The newly created {@link Graphics2D} object.
|
||||
*/
|
||||
public Graphics2D createAppendablePageGraphics2D(int pageIndex, String name) {
|
||||
return pdfBoxDocument.createGraphics(pageIndex, name, true);
|
||||
public Graphics2D createAppendablePageGraphics2D(int pageIndex, String name, NotesPosition notesPosition) {
|
||||
return pdfBoxDocument.createGraphics(pageIndex, name, true, notesPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -294,8 +323,8 @@ public class PdfDocument {
|
|||
* @param pageNumber The page number.
|
||||
* @return The word bounds of the page that has the specified page number.
|
||||
*/
|
||||
public List<Rectangle2D> getNormalizedWordPositions(int pageNumber) {
|
||||
return muPDFDocument.getPageWordsNormalized(pageNumber);
|
||||
public List<Rectangle2D> getNormalizedWordPositions(int pageNumber, NotesPosition splitNotesPosition) {
|
||||
return muPDFDocument.getPageWordsNormalized(pageNumber, splitNotesPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.lecturestudio.core.geometry.Rectangle2D;
|
|||
import org.lecturestudio.core.io.BitConverter;
|
||||
import org.lecturestudio.core.model.DocumentOutline;
|
||||
import org.lecturestudio.core.model.DocumentOutlineItem;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.shape.Shape;
|
||||
import org.lecturestudio.core.pdf.DocumentAdapter;
|
||||
import org.lecturestudio.core.pdf.DocumentRenderer;
|
||||
|
@ -142,6 +143,11 @@ public class MuPDFDocument implements DocumentAdapter {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Graphics2D createGraphics(int pageIndex, String name, boolean appendContent, NotesPosition notesPosition) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTitle(String title) {
|
||||
//doc.setTitle(title);
|
||||
|
@ -167,12 +173,17 @@ public class MuPDFDocument implements DocumentAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getPageBounds(int pageNumber) {
|
||||
public Rectangle2D getPageBounds(int pageNumber, NotesPosition position) {
|
||||
synchronized (mutex) {
|
||||
Page page = getPage(pageNumber);
|
||||
Rect bounds = page.getBounds();
|
||||
try {
|
||||
Page page = getPage(pageNumber);
|
||||
Rect bounds = page.getBounds();
|
||||
|
||||
return new Rectangle2D(0, 0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
|
||||
return new Rectangle2D(0, 0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
return new Rectangle2D();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,12 +210,12 @@ public class MuPDFDocument implements DocumentAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Rectangle2D> getPageWordsNormalized(int pageNumber) {
|
||||
public List<Rectangle2D> getPageWordsNormalized(int pageNumber, NotesPosition splitNotesPosition) {
|
||||
synchronized (mutex) {
|
||||
DisplayList displayList = getDisplayList(pageNumber);
|
||||
Page page = getPage(pageNumber);
|
||||
|
||||
WordWalker wordWalker = new WordWalker(page.getBounds());
|
||||
WordWalker wordWalker = new WordWalker(page.getBounds(), splitNotesPosition);
|
||||
|
||||
StructuredText structuredText = displayList.toStructuredText();
|
||||
structuredText.walk(wordWalker);
|
||||
|
|
|
@ -26,7 +26,7 @@ import com.artifex.mupdf.fitz.Pixmap;
|
|||
import com.artifex.mupdf.fitz.Rect;
|
||||
import com.artifex.mupdf.fitz.RectI;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferInt;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
@ -36,6 +36,7 @@ import java.util.Map;
|
|||
|
||||
import org.lecturestudio.core.geometry.Point2D;
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.pdf.DocumentRenderer;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
|
@ -68,6 +69,9 @@ public class MuPDFRenderer implements DocumentRenderer {
|
|||
synchronized (lock) {
|
||||
Rectangle2D pageRect = parameter.getViewRect();
|
||||
int pageNumber = page.getPageNumber();
|
||||
//Needed for notes on right side
|
||||
float stmX = 0;
|
||||
float ctmX = 0;
|
||||
|
||||
double sx = imageWidth / pageRect.getWidth();
|
||||
double sy = imageHeight / pageRect.getHeight();
|
||||
|
@ -80,19 +84,101 @@ public class MuPDFRenderer implements DocumentRenderer {
|
|||
com.artifex.mupdf.fitz.Page p = document.getPage(pageNumber);
|
||||
Rect bounds = p.getBounds();
|
||||
|
||||
if (page.getDocument().getSplitSlideNotesPosition() == NotesPosition.RIGHT) {
|
||||
bounds.x1 = bounds.x1 / 2;
|
||||
}
|
||||
if (page.getDocument().getSplitSlideNotesPosition() == NotesPosition.LEFT) {
|
||||
bounds.x0 = bounds.x1 / 2;
|
||||
x = (int) (x - (imageWidth - sx));
|
||||
}
|
||||
|
||||
float scale = (float) (1.D / pageRect.getWidth());
|
||||
float pageSx = imageWidth / (bounds.x1 - bounds.x0);
|
||||
float pageSy = imageHeight / (bounds.y1 - bounds.y0);
|
||||
|
||||
if (page.getDocument().getSplitSlideNotesPosition() == NotesPosition.LEFT) {
|
||||
stmX = bounds.x0 * pageSx;
|
||||
ctmX = bounds.x0 * pageSx;
|
||||
}
|
||||
|
||||
Matrix ctm = new Matrix();
|
||||
ctm.translate(-x, -y);
|
||||
//ctm.translate(-x, -y);
|
||||
ctm.translate(-x - ctmX, -y);
|
||||
ctm.scale(pageSx * scale, pageSy * scale);
|
||||
|
||||
int px = (int) (pageRect.getX() * pageSx);
|
||||
int py = (int) (pageRect.getY() * pageSy);
|
||||
|
||||
Matrix stm = new Matrix();
|
||||
stm.translate(-px, -py);
|
||||
//stm.translate(-px, -py);
|
||||
stm.translate(-px - stmX, -py);
|
||||
stm.scale(pageSx, pageSy);
|
||||
|
||||
if (parameter.isTranslation()) {
|
||||
renderPan(parameter, image, displayList, bounds, ctm, stm);
|
||||
}
|
||||
else {
|
||||
RectI scissor = new RectI(bounds).transform(stm);
|
||||
Rect pixmapBounds = new Rect(0, 0, imageWidth, imageHeight);
|
||||
|
||||
renderImage(image, displayList, pixmapBounds, ctm, scissor);
|
||||
|
||||
sizeMap.put(imageWidth, new Point2D(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderNotes(Page page, PresentationParameter parameter,
|
||||
BufferedImage image) throws IOException {
|
||||
int imageWidth = image.getWidth();
|
||||
int imageHeight = image.getHeight();
|
||||
|
||||
synchronized (lock) {
|
||||
Rectangle2D pageRect = parameter.getViewRect();
|
||||
int pageNumber = page.getPageNumber();
|
||||
//Needed for notes on right side
|
||||
float stmX = 0;
|
||||
float ctmX = 0;
|
||||
|
||||
double sx = imageWidth / pageRect.getWidth();
|
||||
double sy = imageHeight / pageRect.getHeight();
|
||||
|
||||
int x = (int) (pageRect.getX() * sx);
|
||||
int y = (int) (pageRect.getY() * sy);
|
||||
|
||||
DisplayList displayList = document.getDisplayList(pageNumber);
|
||||
|
||||
com.artifex.mupdf.fitz.Page p = document.getPage(pageNumber);
|
||||
Rect bounds = p.getBounds();
|
||||
|
||||
if (page.getDocument().getSplitSlideNotesPosition() == NotesPosition.LEFT) {
|
||||
bounds.x1 = bounds.x1 / 2;
|
||||
}
|
||||
if (page.getDocument().getSplitSlideNotesPosition() == NotesPosition.RIGHT) {
|
||||
bounds.x0 = bounds.x1 / 2;
|
||||
}
|
||||
|
||||
float scale = (float) (1.D / pageRect.getWidth());
|
||||
float pageSx = imageWidth / (bounds.x1 - bounds.x0);
|
||||
float pageSy = imageHeight / (bounds.y1 - bounds.y0);
|
||||
|
||||
if (page.getDocument().getSplitSlideNotesPosition() == NotesPosition.RIGHT) {
|
||||
stmX = bounds.x0 * pageSx;
|
||||
ctmX = bounds.x0 * pageSx;
|
||||
}
|
||||
|
||||
Matrix ctm = new Matrix();
|
||||
//ctm.translate(-x, -y);
|
||||
ctm.translate(-x - ctmX, -y);
|
||||
ctm.scale(pageSx * scale, pageSy * scale);
|
||||
|
||||
int px = (int) (pageRect.getX() * pageSx);
|
||||
int py = (int) (pageRect.getY() * pageSy);
|
||||
|
||||
Matrix stm = new Matrix();
|
||||
//stm.translate(-px, -py);
|
||||
stm.translate(-px - stmX, -py);
|
||||
stm.scale(pageSx, pageSy);
|
||||
|
||||
if (parameter.isTranslation()) {
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
|
||||
public class WordWalker implements StructuredTextWalker {
|
||||
|
||||
|
@ -39,13 +40,15 @@ public class WordWalker implements StructuredTextWalker {
|
|||
|
||||
private boolean inBounds = false;
|
||||
|
||||
private NotesPosition splitNotesPosition;
|
||||
|
||||
/**
|
||||
* Create a new {@link WordWalker} with the specified page bounds.
|
||||
*
|
||||
* @param pageBounds The page bounds.
|
||||
*/
|
||||
public WordWalker(Rect pageBounds) {
|
||||
public WordWalker(Rect pageBounds, NotesPosition splitNotesPosition) {
|
||||
this.splitNotesPosition = splitNotesPosition;
|
||||
this.pageBounds = pageBounds;
|
||||
this.scale = 1.F / (pageBounds.x1 - pageBounds.x0);
|
||||
this.boundsList = new ArrayList<>();
|
||||
|
@ -103,12 +106,28 @@ public class WordWalker implements StructuredTextWalker {
|
|||
}
|
||||
|
||||
private void saveWord(Rect wordBounds) {
|
||||
double x = scale * wordBounds.x0;
|
||||
double y = scale * wordBounds.y0;
|
||||
double w = scale * (wordBounds.x1 - wordBounds.x0);
|
||||
double h = scale * (wordBounds.y1 - wordBounds.y0);
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double w = 0;
|
||||
double h = 0;
|
||||
if(splitNotesPosition == NotesPosition.LEFT){
|
||||
x = scale*2 * (wordBounds.x0 - pageBounds.x1/2);
|
||||
y = scale*2 * (wordBounds.y0);
|
||||
w = scale*2 * (wordBounds.x1 - wordBounds.x0);
|
||||
h = scale*2 * (wordBounds.y1 - wordBounds.y0);
|
||||
}else if(splitNotesPosition == NotesPosition.RIGHT){
|
||||
x = scale*2 * wordBounds.x0;
|
||||
y = scale*2 * wordBounds.y0;
|
||||
w = scale*2 * (wordBounds.x1 - wordBounds.x0);
|
||||
h = scale*2 * (wordBounds.y1 - wordBounds.y0);
|
||||
}else{
|
||||
x = scale * wordBounds.x0 ;
|
||||
y = scale * wordBounds.y0;
|
||||
w = scale * (wordBounds.x1 - wordBounds.x0);
|
||||
h = scale * (wordBounds.y1 - wordBounds.y0);
|
||||
}
|
||||
boundsList.add(new Rectangle2D(x, y, w, h));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ import org.lecturestudio.core.geometry.Rectangle2D;
|
|||
import org.lecturestudio.core.io.BitConverter;
|
||||
import org.lecturestudio.core.model.DocumentOutline;
|
||||
import org.lecturestudio.core.model.DocumentOutlineItem;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.shape.Shape;
|
||||
import org.lecturestudio.core.pdf.DocumentAdapter;
|
||||
import org.lecturestudio.core.pdf.DocumentRenderer;
|
||||
|
@ -153,8 +154,20 @@ public class PDFBoxDocument implements DocumentAdapter {
|
|||
|
||||
@Override
|
||||
public PDFGraphics2D createGraphics(int pageIndex, String name, boolean appendContent) {
|
||||
PDPage pdPage = doc.getPage(pageIndex);
|
||||
return createGraphics(pageIndex, name, appendContent, NotesPosition.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PDFGraphics2D createGraphics(int pageIndex, String name, boolean appendContent, NotesPosition notesPosition) {
|
||||
PDPage pdPage = doc.getPage(pageIndex);
|
||||
if(notesPosition == NotesPosition.LEFT){
|
||||
PDRectangle rect = pdPage.getMediaBox();
|
||||
pdPage.setCropBox(new PDRectangle(rect.getWidth()/2, 0, rect.getWidth()/2, rect.getHeight()));
|
||||
}
|
||||
if(notesPosition == NotesPosition.RIGHT){
|
||||
PDRectangle rect = pdPage.getMediaBox();
|
||||
pdPage.setCropBox(new PDRectangle(0, 0, rect.getWidth()/2, rect.getHeight()));
|
||||
}
|
||||
return new PDFGraphics2D(doc, pdPage, name, appendContent);
|
||||
}
|
||||
|
||||
|
@ -179,10 +192,20 @@ public class PDFBoxDocument implements DocumentAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Rectangle2D getPageBounds(int pageNumber) {
|
||||
public Rectangle2D getPageBounds(int pageNumber, NotesPosition position) {
|
||||
PDPage page = doc.getPage(pageNumber);
|
||||
PDRectangle rect = page.getMediaBox();
|
||||
|
||||
if (position == NotesPosition.UNKNOWN) {
|
||||
position = rect.getWidth() / rect.getHeight() >= 2 ? NotesPosition.RIGHT : NotesPosition.UNKNOWN;
|
||||
}
|
||||
if (position == NotesPosition.RIGHT) {
|
||||
return new Rectangle2D(0, 0, rect.getWidth() / 2, rect.getHeight());
|
||||
}
|
||||
if (position == NotesPosition.LEFT) {
|
||||
return new Rectangle2D(rect.getWidth() / 2, 0, rect.getWidth() / 2, rect.getHeight());
|
||||
}
|
||||
|
||||
return new Rectangle2D(0, 0, rect.getWidth(), rect.getHeight());
|
||||
}
|
||||
|
||||
|
@ -199,7 +222,7 @@ public class PDFBoxDocument implements DocumentAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<Rectangle2D> getPageWordsNormalized(int pageNumber) throws IOException {
|
||||
public List<Rectangle2D> getPageWordsNormalized(int pageNumber, NotesPosition splitNotesPosition) throws IOException {
|
||||
WordBoundsExtractor wordExtractor = new WordBoundsExtractor(doc);
|
||||
|
||||
return wordExtractor.getWordBounds(pageNumber + 1);
|
||||
|
@ -351,6 +374,11 @@ public class PDFBoxDocument implements DocumentAdapter {
|
|||
page.setContents(newContents);
|
||||
}
|
||||
|
||||
public void setCropbox(int pageNumber, int x, int y, int width, int height){
|
||||
PDPage page = doc.getPage(pageNumber);
|
||||
page.setCropBox(new PDRectangle(x, y, width, height));
|
||||
}
|
||||
|
||||
public synchronized int importPage(PDFBoxDocument srcDocument, int pageNumber, AffineTransform transform) throws IOException {
|
||||
PDDocument sourceDocument = srcDocument.doc;
|
||||
|
||||
|
@ -359,6 +387,7 @@ public class PDFBoxDocument implements DocumentAdapter {
|
|||
PDPage imported = doc.importPage(page);
|
||||
|
||||
imported.setResources(page.getResources());
|
||||
imported.setMediaBox(imported.getCropBox());
|
||||
|
||||
if (page.getRotation() == 90) {
|
||||
// Set rotation to zero.
|
||||
|
|
|
@ -81,4 +81,9 @@ public class PDFBoxRenderer implements DocumentRenderer {
|
|||
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderNotes(Page page, PresentationParameter parameter, BufferedImage image) throws IOException{
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,6 +256,7 @@ public class DocumentRecorder extends ExecutableBase {
|
|||
}
|
||||
}
|
||||
}
|
||||
recDocument.setActualSplitSlideNotesPosition(pageDoc.getSplitSlideNotesPosition());
|
||||
|
||||
try {
|
||||
PresentationParameter param = paramProvider.getParameter(page);
|
||||
|
|
|
@ -42,12 +42,7 @@ import org.lecturestudio.core.bus.event.DocumentEvent;
|
|||
import org.lecturestudio.core.bus.event.PageEvent;
|
||||
import org.lecturestudio.core.geometry.Dimension2D;
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.DocumentList;
|
||||
import org.lecturestudio.core.model.DocumentType;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.model.RecentDocument;
|
||||
import org.lecturestudio.core.model.TemplateDocument;
|
||||
import org.lecturestudio.core.model.*;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
import org.lecturestudio.core.view.PresentationParameterProvider;
|
||||
import org.lecturestudio.core.view.ViewType;
|
||||
|
@ -192,7 +187,6 @@ public class DocumentService {
|
|||
selectDocument(doc);
|
||||
|
||||
updateRecentDocuments(doc);
|
||||
|
||||
return doc;
|
||||
});
|
||||
}
|
||||
|
@ -407,6 +401,22 @@ public class DocumentService {
|
|||
}
|
||||
}
|
||||
|
||||
public void selectNotesPosition(NotesPosition pos) {
|
||||
Document doc = documents.getSelectedDocument();
|
||||
|
||||
if (nonNull(doc)) {
|
||||
if (!doc.hasNoteSlide()) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.setSplitSlideNotesPosition(pos);
|
||||
doc.calculateCropBox();
|
||||
}
|
||||
|
||||
context.getEventBus().post(new PageEvent(doc.getCurrentPage(),
|
||||
PageEvent.Type.SELECTED));
|
||||
}
|
||||
|
||||
private void selectPage(Document document, int pageNumber) {
|
||||
int currentPageNumber = document.getCurrentPageNumber();
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ public enum ToolType {
|
|||
ELLIPSE,
|
||||
SELECT,
|
||||
SELECT_GROUP,
|
||||
CLONE
|
||||
CLONE,
|
||||
BOOKMARK
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,6 @@ package org.lecturestudio.core.view;
|
|||
|
||||
public enum ViewType {
|
||||
|
||||
Preview, User, Presentation
|
||||
Preview, User, Presentation, Slide_Notes
|
||||
|
||||
}
|
||||
|
|
|
@ -200,7 +200,7 @@ public class PageEventsPresenter extends Presenter<PageEventsView> {
|
|||
|| !previousAction.hasHandle()
|
||||
|| action.getHandle() != previousAction.getHandle()) {
|
||||
if (nonNull(previousAction) && nonNull(previousEndTs)
|
||||
&& Math.abs(action.getTimestamp() - previousEndTs) < 1000
|
||||
&& Math.abs(action.getTimestamp() - previousEndTs) < -1000
|
||||
&& action.getClass().equals(previousAction.getClass())) {
|
||||
// This is a composite action.
|
||||
PageEvent initEvent = eventList.get(eventList.size() - 1);
|
||||
|
|
130
lect-player-web/src/main/frontend/package-lock.json
generated
130
lect-player-web/src/main/frontend/package-lock.json
generated
|
@ -1947,7 +1947,7 @@
|
|||
"angular2-template-loader": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/angular2-template-loader/-/angular2-template-loader-0.6.2.tgz",
|
||||
"integrity": "sha512-jBSrm2yDsTA48GG0H57upn8rmTfJS3/R7EhUeAL/3ryWS8deT9You8UQKWpW4eVSEY7uMJ52iFwpOYXc8QEtGg==",
|
||||
"integrity": "sha1-wNROkP/w+sleiyPwQ6zaf9HFHXw=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^0.2.15"
|
||||
|
@ -1962,7 +1962,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-styles": {
|
||||
|
@ -2114,7 +2114,7 @@
|
|||
"batch": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
|
||||
"integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
|
||||
"integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
|
||||
"dev": true
|
||||
},
|
||||
"big.js": {
|
||||
|
@ -2181,7 +2181,7 @@
|
|||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
||||
"dev": true
|
||||
},
|
||||
"bootstrap": {
|
||||
|
@ -2400,7 +2400,7 @@
|
|||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"color-string": {
|
||||
|
@ -2428,7 +2428,7 @@
|
|||
"commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
|
||||
"dev": true
|
||||
},
|
||||
"compressible": {
|
||||
|
@ -2458,7 +2458,7 @@
|
|||
"bytes": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
|
||||
"integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
|
||||
"integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
|
||||
"dev": true
|
||||
},
|
||||
"debug": {
|
||||
|
@ -2473,7 +2473,7 @@
|
|||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"safe-buffer": {
|
||||
|
@ -2487,7 +2487,7 @@
|
|||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
},
|
||||
"concurrently": {
|
||||
|
@ -2604,7 +2604,7 @@
|
|||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
|
||||
"dev": true
|
||||
},
|
||||
"core-js-compat": {
|
||||
|
@ -2649,7 +2649,7 @@
|
|||
"css-color-names": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
|
||||
"integrity": "sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==",
|
||||
"integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
|
||||
"dev": true
|
||||
},
|
||||
"css-loader": {
|
||||
|
@ -2851,7 +2851,7 @@
|
|||
"dns-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||
"integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
|
||||
"integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
|
||||
"dev": true
|
||||
},
|
||||
"dns-packet": {
|
||||
|
@ -2927,7 +2927,7 @@
|
|||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
|
@ -2945,13 +2945,13 @@
|
|||
"emojis-list": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
|
||||
"integrity": "sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng==",
|
||||
"integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
|
||||
"dev": true
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
|
||||
"dev": true
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
|
@ -3077,13 +3077,13 @@
|
|||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
|
||||
"dev": true
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"eslint-scope": {
|
||||
|
@ -3128,7 +3128,7 @@
|
|||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
|
||||
"dev": true
|
||||
},
|
||||
"eventemitter3": {
|
||||
|
@ -3374,7 +3374,7 @@
|
|||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
|
||||
"dev": true
|
||||
},
|
||||
"fs-extra": {
|
||||
|
@ -3403,7 +3403,7 @@
|
|||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
},
|
||||
"fsevents": {
|
||||
|
@ -3559,7 +3559,7 @@
|
|||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"has-property-descriptors": {
|
||||
|
@ -3607,7 +3607,7 @@
|
|||
"hpack.js": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
|
||||
"integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
|
||||
"integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"inherits": "^2.0.1",
|
||||
|
@ -3651,13 +3651,13 @@
|
|||
"hsl-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A==",
|
||||
"integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=",
|
||||
"dev": true
|
||||
},
|
||||
"hsla-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==",
|
||||
"integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
|
||||
"dev": true
|
||||
},
|
||||
"html-entities": {
|
||||
|
@ -3753,7 +3753,7 @@
|
|||
"http-deceiver": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
|
||||
"integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
|
||||
"integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
|
||||
"dev": true
|
||||
},
|
||||
"http-errors": {
|
||||
|
@ -3849,7 +3849,7 @@
|
|||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
|
@ -3899,7 +3899,7 @@
|
|||
"is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
|
||||
"dev": true
|
||||
},
|
||||
"is-bigint": {
|
||||
|
@ -3939,7 +3939,7 @@
|
|||
"is-color-stop": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz",
|
||||
"integrity": "sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA==",
|
||||
"integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-color-names": "^0.0.4",
|
||||
|
@ -3977,7 +3977,7 @@
|
|||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||
"dev": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
|
@ -4108,19 +4108,19 @@
|
|||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||
"dev": true
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
||||
"dev": true
|
||||
},
|
||||
"isobject": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
|
||||
"integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
|
||||
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
|
||||
"dev": true
|
||||
},
|
||||
"jest-worker": {
|
||||
|
@ -4224,7 +4224,7 @@
|
|||
"loader-utils": {
|
||||
"version": "0.2.17",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
|
||||
"integrity": "sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug==",
|
||||
"integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^3.1.3",
|
||||
|
@ -4236,7 +4236,7 @@
|
|||
"json5": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
|
||||
"integrity": "sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==",
|
||||
"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
@ -4259,13 +4259,13 @@
|
|||
"lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
|
||||
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.topath": {
|
||||
"version": "4.5.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz",
|
||||
"integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==",
|
||||
"integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak=",
|
||||
"dev": true
|
||||
},
|
||||
"lower-case": {
|
||||
|
@ -4307,7 +4307,7 @@
|
|||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
|
||||
"dev": true
|
||||
},
|
||||
"memfs": {
|
||||
|
@ -4322,7 +4322,7 @@
|
|||
"merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
|
||||
"dev": true
|
||||
},
|
||||
"merge-stream": {
|
||||
|
@ -4340,7 +4340,7 @@
|
|||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
|
@ -4491,7 +4491,7 @@
|
|||
"normalize-range": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
|
||||
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
|
||||
"integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=",
|
||||
"dev": true
|
||||
},
|
||||
"npm-run-path": {
|
||||
|
@ -4515,7 +4515,7 @@
|
|||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"dev": true
|
||||
},
|
||||
"object-hash": {
|
||||
|
@ -4584,7 +4584,7 @@
|
|||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
|
@ -4700,7 +4700,7 @@
|
|||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
},
|
||||
"path-key": {
|
||||
|
@ -4718,7 +4718,7 @@
|
|||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
|
@ -4904,7 +4904,7 @@
|
|||
"pretty-hrtime": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
|
||||
"integrity": "sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==",
|
||||
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
|
||||
"dev": true
|
||||
},
|
||||
"process-nextick-args": {
|
||||
|
@ -5127,7 +5127,7 @@
|
|||
"relateurl": {
|
||||
"version": "0.2.7",
|
||||
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
|
||||
"integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
|
||||
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
|
||||
"dev": true
|
||||
},
|
||||
"renderkid": {
|
||||
|
@ -5146,7 +5146,7 @@
|
|||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
|
||||
"dev": true
|
||||
},
|
||||
"require-from-string": {
|
||||
|
@ -5158,7 +5158,7 @@
|
|||
"requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
|
||||
"dev": true
|
||||
},
|
||||
"resize-observer-polyfill": {
|
||||
|
@ -5216,13 +5216,13 @@
|
|||
"rgb-regex": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
|
||||
"integrity": "sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w==",
|
||||
"integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=",
|
||||
"dev": true
|
||||
},
|
||||
"rgba-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==",
|
||||
"integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
|
@ -5381,7 +5381,7 @@
|
|||
"select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
"integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
|
||||
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=",
|
||||
"dev": true
|
||||
},
|
||||
"selfsigned": {
|
||||
|
@ -5457,7 +5457,7 @@
|
|||
"serve-index": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
|
||||
"integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
|
||||
"integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"accepts": "~1.3.4",
|
||||
|
@ -5487,7 +5487,7 @@
|
|||
"http-errors": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
|
||||
"integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
|
||||
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
|
@ -5499,13 +5499,13 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
|
||||
"dev": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
},
|
||||
"setprototypeof": {
|
||||
|
@ -5584,7 +5584,7 @@
|
|||
"simple-swizzle": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
|
||||
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
|
||||
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-arrayish": "^0.3.1"
|
||||
|
@ -5640,7 +5640,7 @@
|
|||
"spawn-command": {
|
||||
"version": "0.0.2-1",
|
||||
"resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz",
|
||||
"integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==",
|
||||
"integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=",
|
||||
"dev": true
|
||||
},
|
||||
"spdy": {
|
||||
|
@ -5738,7 +5738,7 @@
|
|||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
|
@ -6015,7 +6015,7 @@
|
|||
"to-fast-properties": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
|
||||
"integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
|
||||
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
|
@ -6164,7 +6164,7 @@
|
|||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
|
||||
"dev": true
|
||||
},
|
||||
"update-browserslist-db": {
|
||||
|
@ -6189,7 +6189,7 @@
|
|||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
},
|
||||
"util.promisify": {
|
||||
|
@ -6205,13 +6205,13 @@
|
|||
"utila": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
|
||||
"integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
|
||||
"integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=",
|
||||
"dev": true
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
|
||||
"dev": true
|
||||
},
|
||||
"uuid": {
|
||||
|
@ -6223,7 +6223,7 @@
|
|||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
|
||||
"dev": true
|
||||
},
|
||||
"watchpack": {
|
||||
|
@ -6652,7 +6652,7 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
},
|
||||
"ws": {
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.lecturestudio.core.text.TeXFont;
|
|||
import org.lecturestudio.core.text.TextAttributes;
|
||||
import org.lecturestudio.core.tool.PresetColor;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.ParticipantsPosition;
|
||||
import org.lecturestudio.presenter.api.net.ScreenShareProfiles;
|
||||
|
||||
public class DefaultConfiguration extends PresenterConfiguration {
|
||||
|
@ -105,7 +106,7 @@ public class DefaultConfiguration extends PresenterConfiguration {
|
|||
getSlideViewConfiguration().setLeftSliderPosition(0.375);
|
||||
getSlideViewConfiguration().setRightSliderPosition(0.8);
|
||||
getSlideViewConfiguration().setMessageBarPosition(MessageBarPosition.BOTTOM);
|
||||
getSlideViewConfiguration().setParticipantsPosition(MessageBarPosition.LEFT);
|
||||
getSlideViewConfiguration().setParticipantsPosition(ParticipantsPosition.LEFT);
|
||||
|
||||
AudioProcessingSettings processingSettings = new AudioProcessingSettings();
|
||||
processingSettings.setHighpassFilterEnabled(true);
|
||||
|
|
|
@ -45,6 +45,8 @@ public class PresenterConfiguration extends Configuration {
|
|||
|
||||
private final ExternalWindowConfiguration externalSlidePreviewConfig = new ExternalWindowConfiguration();
|
||||
|
||||
private final ExternalWindowConfiguration externalSlideNotesConfig = new ExternalWindowConfiguration();
|
||||
|
||||
private final ExternalWindowConfiguration externalSpeechConfig = new ExternalWindowConfiguration();
|
||||
|
||||
private final ExternalWindowConfiguration externalNotesConfig = new ExternalWindowConfiguration();
|
||||
|
@ -177,4 +179,12 @@ public class PresenterConfiguration extends Configuration {
|
|||
public SlideViewConfiguration getSlideViewConfiguration() {
|
||||
return slideViewConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return External slide notes configuration
|
||||
*/
|
||||
|
||||
public ExternalWindowConfiguration getExternalSlideNotesConfig() {
|
||||
return externalSlideNotesConfig;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,22 +20,27 @@ package org.lecturestudio.presenter.api.config;
|
|||
|
||||
import org.lecturestudio.core.beans.DoubleProperty;
|
||||
import org.lecturestudio.core.beans.ObjectProperty;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.NoteBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
|
||||
public class SlideViewConfiguration {
|
||||
|
||||
private final ObjectProperty<MessageBarPosition> messageBarPosition = new ObjectProperty<>(
|
||||
MessageBarPosition.BOTTOM);
|
||||
|
||||
private final ObjectProperty<NoteBarPosition> notesBarPosition = new ObjectProperty<>(
|
||||
NoteBarPosition.BOTTOM);
|
||||
private final ObjectProperty<SlideNotesPosition> slideNotesPosition = new ObjectProperty<>(
|
||||
SlideNotesPosition.BOTTOM);
|
||||
|
||||
private final ObjectProperty<MessageBarPosition> participantsPosition = new ObjectProperty<>(
|
||||
MessageBarPosition.LEFT);
|
||||
private final ObjectProperty<ParticipantsPosition> participantsPosition = new ObjectProperty<>(
|
||||
ParticipantsPosition.LEFT);
|
||||
|
||||
private final ObjectProperty<MessageBarPosition> previewPosition = new ObjectProperty<>(
|
||||
MessageBarPosition.RIGHT);
|
||||
private final ObjectProperty<SlidePreviewPosition> previewPosition = new ObjectProperty<>(
|
||||
SlidePreviewPosition.RIGHT);
|
||||
|
||||
private final ObjectProperty<NoteSlidePosition> noteSlidePosition = new ObjectProperty<>(
|
||||
NoteSlidePosition.NONE);
|
||||
|
||||
private final ObjectProperty<SpeechPosition> speechPosition = new ObjectProperty<>(
|
||||
SpeechPosition.ABOVE_SLIDE_PREVIEW);
|
||||
|
||||
private final DoubleProperty leftSliderPosition = new DoubleProperty(0.375);
|
||||
|
||||
|
@ -97,41 +102,70 @@ public class SlideViewConfiguration {
|
|||
/**
|
||||
* @return Notes bar's position
|
||||
*/
|
||||
public NoteBarPosition getNotesBarPosition() {
|
||||
return notesBarPosition.get();
|
||||
public SlideNotesPosition getSlideNotesPosition() {
|
||||
return slideNotesPosition.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param position Notes bar's position
|
||||
*/
|
||||
public void setNotesBarPosition(NoteBarPosition position) {
|
||||
notesBarPosition.set(position);
|
||||
public void setSlideNotesPosition(SlideNotesPosition position) {
|
||||
slideNotesPosition.set(position);
|
||||
}
|
||||
|
||||
public MessageBarPosition getParticipantsPosition() {
|
||||
public ParticipantsPosition getParticipantsPosition() {
|
||||
return participantsPosition.get();
|
||||
}
|
||||
|
||||
public void setParticipantsPosition(MessageBarPosition position) {
|
||||
public void setParticipantsPosition(ParticipantsPosition position) {
|
||||
participantsPosition.set(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param position Slide preview position
|
||||
*/
|
||||
public void setPreviewPosition(MessageBarPosition position) {
|
||||
public void setSlidePreviewPosition(SlidePreviewPosition position) {
|
||||
previewPosition.set(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Slide preview position
|
||||
*/
|
||||
public MessageBarPosition getPreviewPosition() {
|
||||
public SlidePreviewPosition getSlidePreviewPosition() {
|
||||
return previewPosition.get();
|
||||
}
|
||||
|
||||
public ObjectProperty<MessageBarPosition> previewPositionProperty() {
|
||||
public ObjectProperty<SlidePreviewPosition> slidePreviewPositionProperty() {
|
||||
return previewPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Slide notes bar's position
|
||||
*/
|
||||
public NoteSlidePosition getNoteSlidePosition() {
|
||||
return noteSlidePosition.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param position Slide notes bar's position
|
||||
*/
|
||||
public void setNoteSlidePosition(NoteSlidePosition position) {
|
||||
noteSlidePosition.set(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the speech position
|
||||
*/
|
||||
public SpeechPosition getSpeechPosition() {
|
||||
return speechPosition.get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param position The speech position
|
||||
*/
|
||||
public void setSpeechPosition(SpeechPosition position) {
|
||||
speechPosition.set(position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* * Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* * Embedded Systems and Applications Group.
|
||||
* *
|
||||
* * 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 <http://www.gnu.org/licenses/>.
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
/**
|
||||
* Handles events for external notes views
|
||||
*
|
||||
* @author Dustin Ringel
|
||||
*/
|
||||
public class ExternalNotesViewEvent extends ExternalViewEvent {
|
||||
public class ExternalNotesViewEvent extends ExternalViewEvent {
|
||||
/**
|
||||
* Creates a new {@code ExternalNotesViewEvent} with the provided parameters.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
*
|
||||
* * Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* * Embedded Systems and Applications Group.
|
||||
* *
|
||||
* * 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
/**
|
||||
* Handles events for external slide notes views
|
||||
*
|
||||
* @author Dustin Ringel
|
||||
*/
|
||||
public class ExternalSlideNotesViewEvent extends ExternalViewEvent {
|
||||
|
||||
/**
|
||||
* Creates a new {@code ExternalSlideNotesViewEvent} with the provided parameters.
|
||||
*
|
||||
* @param enabled Enable the MenuItem
|
||||
*/
|
||||
public ExternalSlideNotesViewEvent(boolean enabled) {
|
||||
super(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code ExternalSlideNotesViewEvent} with the provided parameters.
|
||||
*
|
||||
* @param enabled Enable the MenuItem
|
||||
* @param show Open the external notesViewWindow
|
||||
*/
|
||||
public ExternalSlideNotesViewEvent(boolean enabled, boolean show) {
|
||||
super(enabled, show);
|
||||
}
|
||||
}
|
|
@ -20,9 +20,6 @@ package org.lecturestudio.presenter.api.event;
|
|||
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
|
||||
public class MessageBarPositionEvent extends PositionEvent {
|
||||
public record MessageBarPositionEvent(MessageBarPosition position) {
|
||||
|
||||
public MessageBarPositionEvent(MessageBarPosition position) {
|
||||
super(position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,22 +20,13 @@
|
|||
|
||||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
import org.lecturestudio.presenter.api.model.NoteBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.SlideNotesPosition;
|
||||
|
||||
/**
|
||||
* Handles the position for Notes in a tabbar
|
||||
* Handles the position for Notes in a tab-bar.
|
||||
*
|
||||
* @author Dustin Ringel
|
||||
*/
|
||||
public class NotesBarPositionEvent extends PositionEvent {
|
||||
|
||||
/**
|
||||
* Creates a new {@code NotesBarPositionEvent} with the provided parameters.
|
||||
*
|
||||
* @param position Position of the notes tab
|
||||
*/
|
||||
public NotesBarPositionEvent(NoteBarPosition position) {
|
||||
super(position);
|
||||
}
|
||||
public record NotesBarPositionEvent(SlideNotesPosition position) {
|
||||
|
||||
}
|
||||
|
|
|
@ -18,11 +18,8 @@
|
|||
|
||||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.ParticipantsPosition;
|
||||
|
||||
public class ParticipantsPositionEvent extends PositionEvent {
|
||||
public record ParticipantsPositionEvent(ParticipantsPosition position) {
|
||||
|
||||
public ParticipantsPositionEvent(MessageBarPosition position) {
|
||||
super(position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,8 @@
|
|||
|
||||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.SlidePreviewPosition;
|
||||
|
||||
public class PreviewPositionEvent extends PositionEvent {
|
||||
public record PreviewPositionEvent(SlidePreviewPosition position) {
|
||||
|
||||
public PreviewPositionEvent(MessageBarPosition position) {
|
||||
super(position);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,29 +18,8 @@
|
|||
|
||||
package org.lecturestudio.presenter.api.event;
|
||||
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.NoteBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.NoteSlidePosition;
|
||||
|
||||
public abstract class PositionEvent {
|
||||
public record SlideNotesBarPositionEvent(NoteSlidePosition position) {
|
||||
|
||||
private MessageBarPosition messageBarPosition;
|
||||
|
||||
private NoteBarPosition noteBarPosition;
|
||||
|
||||
|
||||
public PositionEvent(MessageBarPosition messageBarPosition) {
|
||||
this.messageBarPosition = messageBarPosition;
|
||||
}
|
||||
|
||||
public PositionEvent(NoteBarPosition noteBarPosition){
|
||||
this.noteBarPosition = noteBarPosition;
|
||||
}
|
||||
|
||||
public MessageBarPosition getMessageBarPosition() {
|
||||
return messageBarPosition;
|
||||
}
|
||||
|
||||
public NoteBarPosition getNoteBarPosition(){
|
||||
return noteBarPosition;
|
||||
}
|
||||
}
|
|
@ -30,20 +30,30 @@ public enum Shortcut {
|
|||
DOC_OPEN (KeyCode.O, KeyEvent.CTRL_MASK),
|
||||
DOC_CLOSE (KeyCode.F4, KeyEvent.CTRL_MASK),
|
||||
|
||||
SLIDE_FIRST (KeyCode.HOME),
|
||||
SLIDE_LAST (KeyCode.END),
|
||||
|
||||
SLIDE_NEXT_RIGHT (KeyCode.RIGHT),
|
||||
SLIDE_NEXT_DOWN (KeyCode.DOWN),
|
||||
SLIDE_NEXT_PAGE_DOWN (KeyCode.PAGE_DOWN),
|
||||
SLIDE_NEXT_SPACE (KeyCode.SPACE),
|
||||
SLIDE_NEXT_10 (KeyCode.RIGHT, KeyEvent.SHIFT_MASK),
|
||||
SLIDE_PREVIOUS_LEFT (KeyCode.LEFT),
|
||||
SLIDE_PREVIOUS_UP (KeyCode.UP),
|
||||
SLIDE_PREVIOUS_BACK_SPACE (KeyCode.BACK_SPACE),
|
||||
SLIDE_PREVIOUS_PAGE_UP (KeyCode.PAGE_UP),
|
||||
SLIDE_PREVIOUS_10 (KeyCode.LEFT, KeyEvent.SHIFT_MASK),
|
||||
SLIDE_NEW (KeyCode.F9),
|
||||
SLIDE_DELETE (KeyCode.D, KeyEvent.CTRL_MASK),
|
||||
SLIDE_PAN (KeyCode.F11),
|
||||
|
||||
SLIDE_OVERLAY_START (KeyCode.UP, KeyEvent.SHIFT_MASK),
|
||||
SLIDE_OVERLAY_END (KeyCode.DOWN, KeyEvent.SHIFT_MASK),
|
||||
SLIDE_OVERLAY_PREVIOUS (KeyCode.PAGE_UP, KeyEvent.SHIFT_MASK),
|
||||
SLIDE_OVERLAY_NEXT (KeyCode.PAGE_DOWN, KeyEvent.SHIFT_MASK),
|
||||
|
||||
COPY_OVERLAY (KeyCode.V, KeyEvent.CTRL_MASK),
|
||||
COPY_OVERLAY_NEXT_PAGE_CTRL (KeyCode.PAGE_DOWN, KeyEvent.CTRL_MASK),
|
||||
COPY_OVERLAY_NEXT_PAGE_SHIFT (KeyCode.PAGE_DOWN, KeyEvent.SHIFT_MASK),
|
||||
|
||||
UNDO (KeyCode.Z, KeyEvent.CTRL_MASK),
|
||||
REDO (KeyCode.Y, KeyEvent.CTRL_MASK),
|
||||
|
@ -70,6 +80,12 @@ public enum Shortcut {
|
|||
|
||||
BOOKMARK_NEW (KeyCode.B),
|
||||
BOOKMARK_GOTO (KeyCode.G),
|
||||
BOOKMARK_SLIDE (KeyCode.M),
|
||||
BOOKMARK_GOTO_LAST (KeyCode.M, KeyEvent.SHIFT_MASK),
|
||||
|
||||
TIMER_START (KeyCode.S),
|
||||
TIMER_PAUSE (KeyCode.PAUSE),
|
||||
TIMER_RESET (KeyCode.T, KeyEvent.CTRL_MASK),
|
||||
|
||||
COLOR_CUSTOM (KeyCode.F1),
|
||||
COLOR_1 (KeyCode.F2),
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public class BookmarkExistsException extends BookmarkException {
|
||||
|
||||
/**
|
||||
* Constructs a new BookmarkExistsException with the specified detail message.
|
||||
* The cause is not initialized, and may subsequently be initialized by a
|
||||
* call to {@link #initCause}.
|
||||
*
|
||||
* @param message the detail message.
|
||||
*/
|
||||
public BookmarkExistsException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -71,6 +71,16 @@ public class Bookmarks {
|
|||
return bookmarkList;
|
||||
}
|
||||
|
||||
public Bookmark getLastBookmark(Document doc) {
|
||||
List<Bookmark> docBookmarks = bookmarks.get(doc);
|
||||
|
||||
if (isNull(docBookmarks) || docBookmarks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return docBookmarks.get(docBookmarks.size() - 1);
|
||||
}
|
||||
|
||||
public List<Bookmark> getDocumentBookmarks(Document doc) {
|
||||
return bookmarks.get(doc);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public enum MessageBarPosition {
|
||||
|
||||
BOTTOM,
|
||||
LEFT,
|
||||
RIGHT
|
||||
RIGHT,
|
||||
EXTERNAL
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public enum NoteSlidePosition {
|
||||
|
||||
BELOW_SLIDE_PREVIEW,
|
||||
NONE,
|
||||
EXTERNAL
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public enum ParticipantsPosition {
|
||||
|
||||
LEFT,
|
||||
RIGHT,
|
||||
EXTERNAL
|
||||
|
||||
}
|
|
@ -20,12 +20,7 @@
|
|||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
/**
|
||||
* Positions where the note tab can appear
|
||||
*
|
||||
* @author Dustin Ringel
|
||||
*/
|
||||
public enum NoteBarPosition {
|
||||
BOTTOM,
|
||||
LEFT
|
||||
public enum SlideNoteBarPosition {
|
||||
|
||||
BELOW_PREVIEW, NONE
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public enum SlideNotesPosition {
|
||||
|
||||
BOTTOM,
|
||||
LEFT,
|
||||
RIGHT,
|
||||
EXTERNAL
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public enum SlidePreviewPosition {
|
||||
|
||||
LEFT,
|
||||
RIGHT,
|
||||
EXTERNAL
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.model;
|
||||
|
||||
public enum SpeechPosition {
|
||||
|
||||
ABOVE_SLIDE_PREVIEW,
|
||||
EXTERNAL
|
||||
|
||||
}
|
|
@ -62,6 +62,20 @@ public class Stopwatch {
|
|||
timerEnded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the current stopwatch.
|
||||
*/
|
||||
public void startStopwatch() {
|
||||
runStopwatch = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the current stopwatch.
|
||||
*/
|
||||
public void stopStopwatch() {
|
||||
runStopwatch = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switching between running and paused stopwatch.
|
||||
*/
|
||||
|
@ -135,13 +149,6 @@ public class Stopwatch {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the current stopwatch
|
||||
*/
|
||||
public void stopStopwatch() {
|
||||
runStopwatch = false;
|
||||
}
|
||||
|
||||
public StopwatchType getType() {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.lecturestudio.core.presenter.Presenter;
|
|||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkException;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkKeyException;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkExistsException;
|
||||
import org.lecturestudio.presenter.api.model.Bookmarks;
|
||||
import org.lecturestudio.presenter.api.service.BookmarkService;
|
||||
import org.lecturestudio.presenter.api.view.CreateBookmarkView;
|
||||
|
@ -58,10 +59,13 @@ public class CreateBookmarkPresenter extends Presenter<CreateBookmarkView> {
|
|||
bookmarkCreated(bookmarkService.createBookmark(keyStr));
|
||||
}
|
||||
catch (BookmarkKeyException e) {
|
||||
context.showError("bookmark.assign.error", "bookmark.key.exists", keyStr);
|
||||
context.showError("bookmark.assign.warning", "bookmark.key.exists", keyStr);
|
||||
}
|
||||
catch (BookmarkExistsException e){
|
||||
context.showError("bookmark.assign.warning", "bookmark.exists");
|
||||
}
|
||||
catch (BookmarkException e) {
|
||||
handleException(e, "Create bookmark failed", "bookmark.assign.error");
|
||||
handleException(e, "Create bookmark failed", "bookmark.assign.warning");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,22 +21,29 @@ package org.lecturestudio.presenter.api.presenter;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import org.lecturestudio.core.app.ApplicationContext;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.presenter.Presenter;
|
||||
import org.lecturestudio.core.service.DocumentService;
|
||||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkKeyException;
|
||||
import org.lecturestudio.presenter.api.model.Bookmarks;
|
||||
import org.lecturestudio.presenter.api.service.BookmarkService;
|
||||
import org.lecturestudio.presenter.api.view.GotoBookmarkView;
|
||||
|
||||
public class GotoBookmarkPresenter extends Presenter<GotoBookmarkView> {
|
||||
|
||||
private final DocumentService documentService;
|
||||
|
||||
private final BookmarkService bookmarkService;
|
||||
|
||||
private Document selectedDocument;
|
||||
|
||||
|
||||
@Inject
|
||||
GotoBookmarkPresenter(ApplicationContext context, GotoBookmarkView view, BookmarkService bookmarkService) {
|
||||
GotoBookmarkPresenter(ApplicationContext context, GotoBookmarkView view, DocumentService documentService,
|
||||
BookmarkService bookmarkService) {
|
||||
super(context, view);
|
||||
|
||||
this.documentService = documentService;
|
||||
this.bookmarkService = bookmarkService;
|
||||
}
|
||||
|
||||
|
@ -45,9 +52,15 @@ public class GotoBookmarkPresenter extends Presenter<GotoBookmarkView> {
|
|||
Bookmarks bookmarks = bookmarkService.getBookmarks();
|
||||
|
||||
view.setOnClose(this::close);
|
||||
view.setOnGotoPageNumber(this::gotoPageNumber);
|
||||
view.setOnGotoBookmark(this::gotoBookmark);
|
||||
view.setOnDeleteBookmark(this::deleteBookmark);
|
||||
view.setBookmarks(bookmarks.getAllBookmarks());
|
||||
view.setDocument(selectedDocument);
|
||||
}
|
||||
|
||||
public void setSelectedDocument(Document document) {
|
||||
selectedDocument = document;
|
||||
}
|
||||
|
||||
private void deleteBookmark(Bookmark bookmark) {
|
||||
|
@ -61,15 +74,24 @@ public class GotoBookmarkPresenter extends Presenter<GotoBookmarkView> {
|
|||
}
|
||||
|
||||
private void gotoBookmark(Bookmark bookmark) {
|
||||
try {
|
||||
bookmarkService.gotoBookmark(bookmark);
|
||||
close();
|
||||
}
|
||||
catch (BookmarkKeyException e) {
|
||||
if (!bookmarkService.hasBookmark(bookmark)) {
|
||||
context.showError("bookmark.goto.error", "bookmark.key.not.existing", bookmark.getShortcut());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
close();
|
||||
|
||||
bookmarkService.gotoBookmark(bookmark);
|
||||
}
|
||||
catch (Exception e) {
|
||||
handleException(e, "Go to bookmark failed", "bookmark.goto.error");
|
||||
}
|
||||
}
|
||||
|
||||
private void gotoPageNumber(Integer pageNumber) {
|
||||
close();
|
||||
|
||||
documentService.selectPage(pageNumber);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import org.lecturestudio.core.presenter.command.CloseApplicationCommand;
|
|||
import org.lecturestudio.core.presenter.command.ClosePresenterCommand;
|
||||
import org.lecturestudio.core.presenter.command.ShowPresenterCommand;
|
||||
import org.lecturestudio.core.service.DocumentService;
|
||||
import org.lecturestudio.core.util.FileUtils;
|
||||
import org.lecturestudio.core.util.ObservableHashMap;
|
||||
import org.lecturestudio.core.util.ObservableMap;
|
||||
import org.lecturestudio.core.util.ShutdownHandler;
|
||||
|
@ -168,7 +169,18 @@ public class MainPresenter extends org.lecturestudio.core.presenter.MainPresente
|
|||
|
||||
@Override
|
||||
public void openFile(File file) {
|
||||
// No file associations yet.
|
||||
if (isNull(file)) {
|
||||
return;
|
||||
}
|
||||
showWaitingNotification("open.document");
|
||||
documentService.openDocument(file).thenRun( () -> {
|
||||
hideWaitingNotification();
|
||||
}).exceptionally(throwable -> {
|
||||
hideWaitingNotification();
|
||||
handleException(throwable, "Open document failed",
|
||||
"open.document.error", file.getPath());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,12 +28,10 @@ import java.awt.Desktop;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
@ -46,14 +44,11 @@ import org.lecturestudio.core.app.ApplicationContext;
|
|||
import org.lecturestudio.core.app.configuration.Configuration;
|
||||
import org.lecturestudio.core.app.dictionary.Dictionary;
|
||||
import org.lecturestudio.core.audio.AudioDeviceNotConnectedException;
|
||||
import org.lecturestudio.core.beans.ObjectProperty;
|
||||
import org.lecturestudio.core.bus.EventBus;
|
||||
import org.lecturestudio.core.bus.event.CustomizeToolbarEvent;
|
||||
import org.lecturestudio.core.bus.event.DocumentEvent;
|
||||
import org.lecturestudio.core.bus.event.PageEvent;
|
||||
import org.lecturestudio.core.bus.event.ViewVisibleEvent;
|
||||
import org.lecturestudio.core.bus.event.*;
|
||||
import org.lecturestudio.core.controller.ToolController;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.model.RecentDocument;
|
||||
import org.lecturestudio.core.model.listener.PageEditEvent;
|
||||
|
@ -67,23 +62,20 @@ import org.lecturestudio.core.service.DocumentService;
|
|||
import org.lecturestudio.core.util.FileUtils;
|
||||
import org.lecturestudio.core.util.ListChangeListener;
|
||||
import org.lecturestudio.core.util.ObservableList;
|
||||
import org.lecturestudio.core.view.FileChooserView;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
import org.lecturestudio.core.view.PresentationParameterProvider;
|
||||
import org.lecturestudio.core.view.View;
|
||||
import org.lecturestudio.core.view.ViewContextFactory;
|
||||
import org.lecturestudio.core.view.ViewType;
|
||||
import org.lecturestudio.core.view.*;
|
||||
import org.lecturestudio.presenter.api.config.PresenterConfiguration;
|
||||
import org.lecturestudio.presenter.api.config.SlideViewConfiguration;
|
||||
import org.lecturestudio.presenter.api.context.PresenterContext;
|
||||
import org.lecturestudio.presenter.api.event.ExternalMessagesViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalNotesViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalSlideNotesViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalParticipantsViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalSlidePreviewViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalSpeechViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.MessageBarPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.MessengerStateEvent;
|
||||
import org.lecturestudio.presenter.api.event.NotesBarPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.SlideNotesBarPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.ParticipantsPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.PreviewPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.QuizStateEvent;
|
||||
|
@ -91,13 +83,8 @@ import org.lecturestudio.presenter.api.event.RecordingStateEvent;
|
|||
import org.lecturestudio.presenter.api.event.RecordingTimeEvent;
|
||||
import org.lecturestudio.presenter.api.event.StreamReconnectStateEvent;
|
||||
import org.lecturestudio.presenter.api.event.StreamingStateEvent;
|
||||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkKeyException;
|
||||
import org.lecturestudio.presenter.api.model.Bookmarks;
|
||||
import org.lecturestudio.presenter.api.model.BookmarksListener;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.NoteBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.Stopwatch;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
import org.lecturestudio.presenter.api.presenter.command.GotoBookmarkCommand;
|
||||
import org.lecturestudio.presenter.api.presenter.command.StopwatchCommand;
|
||||
import org.lecturestudio.presenter.api.service.BookmarkService;
|
||||
import org.lecturestudio.presenter.api.service.QuizWebServiceState;
|
||||
|
@ -111,6 +98,8 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
/** Mainly used for Desktop.getDesktop().open to circumvent errors. */
|
||||
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
private final Map<Class<?>, Object> viewPositionMap = new HashMap<>();
|
||||
|
||||
private final DateTimeFormatter timeFormatter;
|
||||
|
||||
private final Timer timer;
|
||||
|
@ -159,6 +148,10 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
|
||||
view.setDocument(doc);
|
||||
|
||||
if (nonNull(doc)) {
|
||||
view.setSplitNotesPosition(doc.getSplitSlideNotesPosition());
|
||||
}
|
||||
|
||||
pageChanged(page);
|
||||
}
|
||||
|
||||
|
@ -230,27 +223,62 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
|
||||
@Subscribe
|
||||
public void onEvent(final ExternalMessagesViewEvent event) {
|
||||
view.setExternalMessages(event.isEnabled(), event.isShow());
|
||||
if (!event.isEnabled()) {
|
||||
// Set the previous position.
|
||||
MessageBarPosition position = getViewPosition(MessageBarPosition.class);
|
||||
|
||||
if (nonNull(position)) {
|
||||
view.setMessagesPosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final ExternalParticipantsViewEvent event) {
|
||||
view.setExternalParticipants(event.isEnabled(), event.isShow());
|
||||
if (!event.isEnabled()) {
|
||||
// Set the previous position.
|
||||
ParticipantsPosition position = getViewPosition(ParticipantsPosition.class);
|
||||
|
||||
if (nonNull(position)) {
|
||||
view.setParticipantsPosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final ExternalSlidePreviewViewEvent event) {
|
||||
view.setExternalSlidePreview(event.isEnabled(), event.isShow());
|
||||
}
|
||||
if (!event.isEnabled()) {
|
||||
// Set the previous position.
|
||||
SlidePreviewPosition position = getViewPosition(SlidePreviewPosition.class);
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final ExternalSpeechViewEvent event) {
|
||||
view.setExternalSpeech(event.isEnabled(), event.isShow());
|
||||
if (nonNull(position)) {
|
||||
view.setSlidePreviewPosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final ExternalNotesViewEvent event) {
|
||||
view.setExternalNotes(event.isEnabled(), event.isShow());
|
||||
if (!event.isEnabled()) {
|
||||
// Set the previous position.
|
||||
SlideNotesPosition position = getViewPosition(SlideNotesPosition.class);
|
||||
|
||||
if (nonNull(position)) {
|
||||
view.setSlideNotesPosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final ExternalSlideNotesViewEvent event) {
|
||||
if (!event.isEnabled()) {
|
||||
// Set the previous position.
|
||||
NoteSlidePosition position = getViewPosition(NoteSlidePosition.class);
|
||||
|
||||
if (nonNull(position)) {
|
||||
view.setNoteSlidePosition(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void openBookmark(Bookmark bookmark) {
|
||||
|
@ -265,6 +293,20 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
}
|
||||
}
|
||||
|
||||
public void openPrevBookmark(){
|
||||
Page page = bookmarkService.getPrevBookmarkPage();
|
||||
if (nonNull(page)) {
|
||||
documentService.selectPage(page);
|
||||
}
|
||||
}
|
||||
|
||||
public void openNextBookmark(){
|
||||
Page page = bookmarkService.getNextBookmarkPage();
|
||||
if (nonNull(page)) {
|
||||
documentService.selectPage(page);
|
||||
}
|
||||
}
|
||||
|
||||
public void openDocument(File documentFile) {
|
||||
documentService.openDocument(documentFile)
|
||||
.exceptionally(throwable -> {
|
||||
|
@ -301,36 +343,84 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
eventBus.post(new CustomizeToolbarEvent());
|
||||
}
|
||||
|
||||
public void externalMessages(boolean selected) {
|
||||
eventBus.post(new ExternalMessagesViewEvent(selected));
|
||||
}
|
||||
public void positionSpeech(SpeechPosition position) {
|
||||
if (position == SpeechPosition.EXTERNAL) {
|
||||
eventBus.post(new ExternalSpeechViewEvent(true));
|
||||
|
||||
public void externalParticipants(boolean selected) {
|
||||
eventBus.post(new ExternalParticipantsViewEvent(selected));
|
||||
}
|
||||
|
||||
public void externalSlidePreview(boolean selected) {
|
||||
eventBus.post(new ExternalSlidePreviewViewEvent(selected));
|
||||
}
|
||||
|
||||
public void externalSpeech(boolean selected) {
|
||||
eventBus.post(new ExternalSpeechViewEvent(selected));
|
||||
}
|
||||
|
||||
public void externalNotes(boolean selected) {
|
||||
eventBus.post(new ExternalNotesViewEvent(selected));
|
||||
// getPresenterConfig().getSlideViewConfiguration().setSpeechPosition(position);
|
||||
}
|
||||
else {
|
||||
setViewPosition(SpeechPosition.class, position);
|
||||
}
|
||||
}
|
||||
|
||||
public void positionMessages(MessageBarPosition position) {
|
||||
eventBus.post(new MessageBarPositionEvent(position));
|
||||
if (position == MessageBarPosition.EXTERNAL) {
|
||||
eventBus.post(new ExternalMessagesViewEvent(true));
|
||||
|
||||
// getPresenterConfig().getSlideViewConfiguration().setMessageBarPosition(position);
|
||||
}
|
||||
else {
|
||||
setViewPosition(MessageBarPosition.class, position);
|
||||
|
||||
eventBus.post(new MessageBarPositionEvent(position));
|
||||
}
|
||||
}
|
||||
|
||||
public void positionNotes(NoteBarPosition position) {
|
||||
eventBus.post(new NotesBarPositionEvent(position));
|
||||
public void positionParticipants(ParticipantsPosition position) {
|
||||
if (position == ParticipantsPosition.EXTERNAL) {
|
||||
eventBus.post(new ExternalParticipantsViewEvent(true));
|
||||
|
||||
// getPresenterConfig().getSlideViewConfiguration().setParticipantsPosition(position);
|
||||
}
|
||||
else {
|
||||
setViewPosition(ParticipantsPosition.class, position);
|
||||
|
||||
eventBus.post(new ParticipantsPositionEvent(position));
|
||||
}
|
||||
}
|
||||
|
||||
public void positionParticipants(MessageBarPosition position) {
|
||||
eventBus.post(new ParticipantsPositionEvent(position));
|
||||
public void positionSlidePreview(SlidePreviewPosition position) {
|
||||
if (position == SlidePreviewPosition.EXTERNAL) {
|
||||
eventBus.post(new ExternalSlidePreviewViewEvent(true));
|
||||
|
||||
// getPresenterConfig().getSlideViewConfiguration().setSlidePreviewPosition(position);
|
||||
}
|
||||
else {
|
||||
setViewPosition(SlidePreviewPosition.class, position);
|
||||
|
||||
eventBus.post(new PreviewPositionEvent(position));
|
||||
}
|
||||
}
|
||||
|
||||
public void positionSlideNotes(SlideNotesPosition position) {
|
||||
if (position == SlideNotesPosition.EXTERNAL) {
|
||||
eventBus.post(new ExternalNotesViewEvent(true));
|
||||
|
||||
// getPresenterConfig().getSlideViewConfiguration().setSlideNotesPosition(position);
|
||||
}
|
||||
else {
|
||||
setViewPosition(SlideNotesPosition.class, position);
|
||||
|
||||
eventBus.post(new NotesBarPositionEvent(position));
|
||||
}
|
||||
}
|
||||
|
||||
public void positionNoteSlide(NoteSlidePosition position) {
|
||||
if (position == NoteSlidePosition.EXTERNAL) {
|
||||
eventBus.post(new ExternalSlideNotesViewEvent(true));
|
||||
|
||||
// getPresenterConfig().getSlideViewConfiguration().setNoteSlidePosition(position);
|
||||
}
|
||||
else {
|
||||
setViewPosition(NoteSlidePosition.class, position);
|
||||
|
||||
eventBus.post(new SlideNotesBarPositionEvent(position));
|
||||
}
|
||||
}
|
||||
|
||||
public void positionSplitNotes(NotesPosition position){
|
||||
documentService.selectNotesPosition(position);
|
||||
}
|
||||
|
||||
public void newWhiteboard() {
|
||||
|
@ -430,8 +520,52 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
eventBus.post(new ShowPresenterCommand<>(CreateBookmarkPresenter.class));
|
||||
}
|
||||
|
||||
public void newDefaultBookmark() {
|
||||
try {
|
||||
bookmarkCreated(bookmarkService.createDefaultBookmark());
|
||||
}
|
||||
catch (BookmarkExistsException e) {
|
||||
Page page = documentService.getDocuments().getSelectedDocument().getCurrentPage();
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.exists"), page.getPageNumber());
|
||||
context.showNotification(NotificationType.WARNING, "bookmark.assign.warning", message);
|
||||
}
|
||||
catch (BookmarkException e) {
|
||||
handleException(e, "Create bookmark failed", "bookmark.assign.warning");
|
||||
}
|
||||
}
|
||||
|
||||
public void removeBookmark() {
|
||||
try {
|
||||
if (nonNull(bookmarkService.getPageBookmark())) {
|
||||
String shortcut = bookmarkService.getPageBookmark().getShortcut();
|
||||
bookmarkService.deleteBookmark(bookmarkService.getPageBookmark());
|
||||
bookmarkRemoved(shortcut);
|
||||
}
|
||||
}
|
||||
catch (BookmarkException e) {
|
||||
handleException(e, "Remove bookmark failed", "bookmark.assign.warning");
|
||||
}
|
||||
}
|
||||
private void bookmarkRemoved(String shortcut) {
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.removed"), shortcut);
|
||||
|
||||
context.showNotificationPopup(message);
|
||||
close();
|
||||
}
|
||||
|
||||
|
||||
private void bookmarkCreated(Bookmark bookmark) {
|
||||
String shortcut = bookmark.getShortcut().toUpperCase();
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.created"), shortcut);
|
||||
|
||||
context.showNotificationPopup(message);
|
||||
close();
|
||||
}
|
||||
|
||||
public void gotoBookmark() {
|
||||
eventBus.post(new ShowPresenterCommand<>(GotoBookmarkPresenter.class));
|
||||
Document selectedDoc = documentService.getDocuments().getSelectedDocument();
|
||||
|
||||
eventBus.post(new GotoBookmarkCommand(selectedDoc));
|
||||
}
|
||||
|
||||
public void previousBookmark() {
|
||||
|
@ -508,6 +642,15 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
return (PresenterConfiguration) context.getConfiguration();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T getViewPosition(Class<T> cls) {
|
||||
return (T) viewPositionMap.getOrDefault(cls, null);
|
||||
}
|
||||
|
||||
private <T> void setViewPosition(Class<T> cls, T value) {
|
||||
viewPositionMap.put(cls, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
final PresenterContext presenterContext = (PresenterContext) context;
|
||||
|
@ -516,6 +659,13 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
|
||||
eventBus.register(this);
|
||||
|
||||
setViewPosition(MessageBarPosition.class, slideViewConfig.getMessageBarPosition());
|
||||
setViewPosition(ParticipantsPosition.class, slideViewConfig.getParticipantsPosition());
|
||||
setViewPosition(SlidePreviewPosition.class, slideViewConfig.getSlidePreviewPosition());
|
||||
setViewPosition(SlideNotesPosition.class, slideViewConfig.getSlideNotesPosition());
|
||||
setViewPosition(NoteSlidePosition.class, slideViewConfig.getNoteSlidePosition());
|
||||
setViewPosition(SpeechPosition.class, slideViewConfig.getSpeechPosition());
|
||||
|
||||
view.setRecordingState(ExecutableState.Stopped);
|
||||
view.setMessengerState(ExecutableState.Stopped);
|
||||
view.setStreamingState(ExecutableState.Stopped);
|
||||
|
@ -543,44 +693,26 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
|
||||
view.setOnCustomizeToolbar(this::customizeToolbar);
|
||||
|
||||
view.setOnExternalMessages(this::externalMessages);
|
||||
view.setOnExternalParticipants(this::externalParticipants);
|
||||
view.setOnExternalSlidePreview(this::externalSlidePreview);
|
||||
view.setOnExternalSpeech(this::externalSpeech);
|
||||
view.setOnExternalNotes(this::externalNotes);
|
||||
view.setSpeechPosition(slideViewConfig.getSpeechPosition());
|
||||
view.setOnSpeechPosition(this::positionSpeech);
|
||||
|
||||
switch (slideViewConfig.getMessageBarPosition()) {
|
||||
case LEFT -> view.setMessagesPositionLeft();
|
||||
case BOTTOM -> view.setMessagesPositionBottom();
|
||||
case RIGHT -> view.setMessagesPositionRight();
|
||||
}
|
||||
view.setMessagesPosition(slideViewConfig.getMessageBarPosition());
|
||||
view.setOnMessagesPosition(this::positionMessages);
|
||||
|
||||
view.setOnMessagesPositionLeft(() -> positionMessages(MessageBarPosition.LEFT));
|
||||
view.setOnMessagesPositionBottom(() -> positionMessages(MessageBarPosition.BOTTOM));
|
||||
view.setOnMessagesPositionRight(() -> positionMessages(MessageBarPosition.RIGHT));
|
||||
view.setSlideNotesPosition(slideViewConfig.getSlideNotesPosition());
|
||||
view.setOnSlideNotesPosition(this::positionSlideNotes);
|
||||
|
||||
switch (slideViewConfig.getNotesBarPosition()) {
|
||||
case LEFT -> view.setNotesPositionLeft();
|
||||
case BOTTOM -> view.setNotesPositionBottom();
|
||||
}
|
||||
view.setNoteSlidePosition(slideViewConfig.getNoteSlidePosition());
|
||||
view.setOnNoteSlidePosition(this::positionNoteSlide);
|
||||
|
||||
view.setOnNotesPositionLeft(() -> positionNotes(NoteBarPosition.LEFT));
|
||||
view.setOnNotesPositionBottom(() -> positionNotes(NoteBarPosition.BOTTOM));
|
||||
view.setParticipantsPosition(slideViewConfig.getParticipantsPosition());
|
||||
view.setOnParticipantsPosition(this::positionParticipants);
|
||||
|
||||
switch (slideViewConfig.getParticipantsPosition()) {
|
||||
case LEFT -> view.setParticipantsPositionLeft();
|
||||
case RIGHT -> view.setParticipantsPositionRight();
|
||||
}
|
||||
view.setSlidePreviewPosition(slideViewConfig.getSlidePreviewPosition());
|
||||
view.setOnSlidePreviewPosition(this::positionSlidePreview);
|
||||
|
||||
view.setOnParticipantsPositionLeft(() -> positionParticipants(MessageBarPosition.LEFT));
|
||||
view.setOnParticipantsPositionRight(() -> positionParticipants(MessageBarPosition.RIGHT));
|
||||
|
||||
ObjectProperty<MessageBarPosition> previewPosition = slideViewConfig.previewPositionProperty();
|
||||
previewPosition.addListener((o, oldPos, newPos) -> {
|
||||
eventBus.post(new PreviewPositionEvent(newPos));
|
||||
});
|
||||
|
||||
view.bindPreviewPosition(previewPosition);
|
||||
view.setSplitNotesPosition(NotesPosition.NONE);
|
||||
view.setOnSplitNotesPosition(this::positionSplitNotes);
|
||||
|
||||
view.setOnNewWhiteboard(this::newWhiteboard);
|
||||
view.setOnNewWhiteboardPage(this::newWhiteboardPage);
|
||||
|
@ -605,8 +737,12 @@ public class MenuPresenter extends Presenter<MenuView> {
|
|||
|
||||
view.setOnClearBookmarks(this::clearBookmarks);
|
||||
view.setOnShowNewBookmarkView(this::newBookmark);
|
||||
view.setOnRemoveBookmarkView(this::removeBookmark);
|
||||
view.setOnCreateNewDefaultBookmarkView(this::newDefaultBookmark);
|
||||
view.setOnShowGotoBookmarkView(this::gotoBookmark);
|
||||
view.setOnPreviousBookmark(this::previousBookmark);
|
||||
view.setOnPrevBookmark(this::openPrevBookmark);
|
||||
view.setOnNextBookmark(this::openNextBookmark);
|
||||
view.setOnOpenBookmark(this::openBookmark);
|
||||
|
||||
view.setOnOpenLog(this::showLog);
|
||||
|
|
|
@ -27,6 +27,7 @@ import javax.inject.Inject;
|
|||
import java.awt.Dimension;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -90,15 +91,18 @@ import org.lecturestudio.core.view.ViewType;
|
|||
import org.lecturestudio.presenter.api.config.DocumentTemplateConfiguration;
|
||||
import org.lecturestudio.presenter.api.config.ExternalWindowConfiguration;
|
||||
import org.lecturestudio.presenter.api.config.PresenterConfiguration;
|
||||
import org.lecturestudio.presenter.api.config.SlideViewConfiguration;
|
||||
import org.lecturestudio.presenter.api.context.PresenterContext;
|
||||
import org.lecturestudio.presenter.api.event.ExternalMessagesViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalNotesViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalSlideNotesViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalParticipantsViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalSlidePreviewViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.ExternalSpeechViewEvent;
|
||||
import org.lecturestudio.presenter.api.event.MessageBarPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.MessengerStateEvent;
|
||||
import org.lecturestudio.presenter.api.event.NotesBarPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.SlideNotesBarPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.ParticipantsPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.PreviewPositionEvent;
|
||||
import org.lecturestudio.presenter.api.event.QuizStateEvent;
|
||||
|
@ -108,13 +112,8 @@ import org.lecturestudio.presenter.api.event.ScreenShareStateEvent;
|
|||
import org.lecturestudio.presenter.api.event.StreamReconnectStateEvent;
|
||||
import org.lecturestudio.presenter.api.event.StreamingStateEvent;
|
||||
import org.lecturestudio.presenter.api.input.Shortcut;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.MessageDocument;
|
||||
import org.lecturestudio.presenter.api.model.NoteBarPosition;
|
||||
import org.lecturestudio.presenter.api.service.RecordingService;
|
||||
import org.lecturestudio.presenter.api.service.WebRtcStreamService;
|
||||
import org.lecturestudio.presenter.api.service.WebService;
|
||||
import org.lecturestudio.presenter.api.service.WebServiceInfo;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
import org.lecturestudio.presenter.api.service.*;
|
||||
import org.lecturestudio.presenter.api.view.SlidesView;
|
||||
import org.lecturestudio.swing.model.ExternalWindowPosition;
|
||||
import org.lecturestudio.web.api.event.LocalScreenVideoFrameEvent;
|
||||
|
@ -161,6 +160,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
private final RenderController renderController;
|
||||
|
||||
private final BookmarkService bookmarkService;
|
||||
|
||||
private final DocumentService documentService;
|
||||
|
||||
private final RecordingService recordingService;
|
||||
|
@ -190,6 +191,7 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
ToolController toolController,
|
||||
PresentationController presentationController,
|
||||
RenderController renderController,
|
||||
BookmarkService bookmarkService,
|
||||
DocumentService documentService,
|
||||
DocumentRecorder documentRecorder,
|
||||
RecordingService recordingService,
|
||||
|
@ -203,6 +205,7 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
this.presentationController = presentationController;
|
||||
this.renderController = renderController;
|
||||
this.documentRecorder = documentRecorder;
|
||||
this.bookmarkService = bookmarkService;
|
||||
this.documentService = documentService;
|
||||
this.recordingService = recordingService;
|
||||
this.webService = webService;
|
||||
|
@ -488,9 +491,24 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(ExternalSlideNotesViewEvent event) {
|
||||
if (event.isEnabled()) {
|
||||
if (event.isShow()) {
|
||||
viewShowExternalSlideNotes(event.isPersistent());
|
||||
}
|
||||
else {
|
||||
view.hideExternalSlideNotes();
|
||||
}
|
||||
}
|
||||
else {
|
||||
viewHideExternalSlideNotes(event.isPersistent());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(MessageBarPositionEvent event) {
|
||||
final MessageBarPosition position = event.getMessageBarPosition();
|
||||
final MessageBarPosition position = event.position();
|
||||
|
||||
view.setMessageBarPosition(position);
|
||||
|
||||
|
@ -499,7 +517,7 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
@Subscribe
|
||||
public void onEvent(ParticipantsPositionEvent event) {
|
||||
final MessageBarPosition position = event.getMessageBarPosition();
|
||||
final ParticipantsPosition position = event.position();
|
||||
|
||||
view.setParticipantsPosition(position);
|
||||
|
||||
|
@ -508,18 +526,25 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
@Subscribe
|
||||
public void onEvent(PreviewPositionEvent event) {
|
||||
final MessageBarPosition position = event.getMessageBarPosition();
|
||||
|
||||
view.setPreviewPosition(position);
|
||||
view.setPreviewPosition(event.position());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(NotesBarPositionEvent event) {
|
||||
final NoteBarPosition position = event.getNoteBarPosition();
|
||||
final SlideNotesPosition position = event.position();
|
||||
|
||||
view.setNotesBarPosition(position);
|
||||
view.setNotesPosition(position);
|
||||
|
||||
getPresenterConfig().getSlideViewConfiguration().setNotesBarPosition(position);
|
||||
getPresenterConfig().getSlideViewConfiguration().setSlideNotesPosition(position);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(SlideNotesBarPositionEvent event) {
|
||||
final NoteSlidePosition position = event.position();
|
||||
|
||||
view.setNoteSlidePosition(position);
|
||||
|
||||
getPresenterConfig().getSlideViewConfiguration().setNoteSlidePosition(position);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
@ -615,6 +640,21 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
eventBus.post(new ExternalNotesViewEvent(false));
|
||||
}
|
||||
|
||||
private void externalSlideNotesPositionChanged(ExternalWindowPosition position) {
|
||||
final ExternalWindowConfiguration config = getExternalSlideNotesConfig();
|
||||
|
||||
config.setPosition(position.getPosition());
|
||||
config.setScreen(position.getScreen());
|
||||
}
|
||||
|
||||
private void externalSlideNotesSizeChanged(Dimension size) {
|
||||
getExternalSlideNotesConfig().setSize(size);
|
||||
}
|
||||
|
||||
private void externalSlideNotesClosed() {
|
||||
eventBus.post(new ExternalSlideNotesViewEvent(false));
|
||||
}
|
||||
|
||||
private void keyEvent(KeyEvent event) {
|
||||
Action action = shortcutMap.get(event);
|
||||
|
||||
|
@ -850,14 +890,158 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
idleTimer.runIdleTask();
|
||||
}
|
||||
|
||||
private void firstPage() {
|
||||
documentService.selectPage(0);
|
||||
}
|
||||
|
||||
private void lastPage() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
|
||||
documentService.selectPage(doc.getPageCount() - 1);
|
||||
}
|
||||
|
||||
private void nextPage() {
|
||||
documentService.selectNextPage();
|
||||
}
|
||||
|
||||
private void tenPagesForward() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
int pageNumber = Math.min(doc.getCurrentPageNumber() + 10, doc.getPageCount() - 1);
|
||||
|
||||
documentService.selectPage(pageNumber);
|
||||
}
|
||||
|
||||
private void previousPage() {
|
||||
documentService.selectPreviousPage();
|
||||
}
|
||||
|
||||
private void tenPagesBack() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
int pageNumber = Math.max(doc.getCurrentPageNumber() - 10, 0);
|
||||
|
||||
documentService.selectPage(pageNumber);
|
||||
}
|
||||
|
||||
private void overlayStart() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
Page page = doc.getCurrentPage();
|
||||
|
||||
if (page.isOverlay()) {
|
||||
Page lastOverlay = null;
|
||||
var listIter = doc.getPages().listIterator(doc.getPageIndex(page));
|
||||
|
||||
while (listIter.hasPrevious()) {
|
||||
Page previous = listIter.previous();
|
||||
if (!previous.isOverlay() && nonNull(lastOverlay)) {
|
||||
documentService.selectPage(lastOverlay);
|
||||
break;
|
||||
}
|
||||
|
||||
lastOverlay = previous;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void overlayEnd() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
Page page = doc.getCurrentPage();
|
||||
|
||||
if (page.isOverlay()) {
|
||||
Page lastOverlay = null;
|
||||
var listIter = doc.getPages().listIterator(doc.getPageIndex(page));
|
||||
|
||||
while (listIter.hasNext()) {
|
||||
Page next = listIter.next();
|
||||
if (!next.isOverlay() && nonNull(lastOverlay)) {
|
||||
documentService.selectPage(lastOverlay);
|
||||
break;
|
||||
}
|
||||
|
||||
lastOverlay = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void overlayPreviousPage() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
Page page = doc.getCurrentPage();
|
||||
|
||||
if (page.isOverlay()) {
|
||||
var listIter = doc.getPages().listIterator(doc.getPageIndex(page));
|
||||
|
||||
while (listIter.hasPrevious()) {
|
||||
Page previous = listIter.previous();
|
||||
if (!previous.isOverlay()) {
|
||||
documentService.selectPage(previous);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void overlayNextPage() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
Page page = doc.getCurrentPage();
|
||||
|
||||
if (page.isOverlay()) {
|
||||
var listIter = doc.getPages().listIterator(doc.getPageIndex(page));
|
||||
|
||||
while (listIter.hasNext()) {
|
||||
Page next = listIter.next();
|
||||
if (!next.isOverlay()) {
|
||||
documentService.selectPage(next);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bookmarkSlide() {
|
||||
try {
|
||||
bookmarkCreated(bookmarkService.createDefaultBookmark());
|
||||
}
|
||||
catch (BookmarkException e) {
|
||||
handleException(e, "Create bookmark failed", "bookmark.assign.warning", "bookmark.exists");
|
||||
}
|
||||
}
|
||||
|
||||
private void bookmarkGotoLastSlide() {
|
||||
Document doc = documentService.getDocuments().getSelectedDocument();
|
||||
Bookmark bookmark = bookmarkService.getBookmarks().getLastBookmark(doc);
|
||||
|
||||
if (nonNull(bookmark)) {
|
||||
try {
|
||||
bookmarkService.gotoBookmark(bookmark);
|
||||
}
|
||||
catch (BookmarkException e) {
|
||||
handleException(e, "Go to bookmark failed", "bookmark.goto.error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bookmarkCreated(Bookmark bookmark) {
|
||||
String shortcut = bookmark.getShortcut().toUpperCase();
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.created"), shortcut);
|
||||
|
||||
context.showNotificationPopup(message);
|
||||
close();
|
||||
}
|
||||
|
||||
private void timerStart() {
|
||||
PresenterContext pContext = (PresenterContext) context;
|
||||
pContext.getStopwatch().startStopwatch();
|
||||
}
|
||||
|
||||
private void timerPause() {
|
||||
PresenterContext pContext = (PresenterContext) context;
|
||||
pContext.getStopwatch().stopStopwatch();
|
||||
}
|
||||
|
||||
private void timerReset() {
|
||||
PresenterContext pContext = (PresenterContext) context;
|
||||
pContext.getStopwatch().resetStopwatch();
|
||||
}
|
||||
|
||||
private void registerShortcut(Shortcut shortcut, Action action) {
|
||||
shortcutMap.put(shortcut.getKeyEvent(), action);
|
||||
}
|
||||
|
@ -939,6 +1123,8 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
for(String note : page.getNotes()){
|
||||
view.setNotesText(note);
|
||||
}
|
||||
|
||||
view.setSlideNotes(page, parameter);
|
||||
loadPageObjectViews(page);
|
||||
|
||||
recordPage(page);
|
||||
|
@ -978,7 +1164,7 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
}
|
||||
|
||||
private PageObjectView<? extends Shape> createPageObjectView(Shape shape,
|
||||
Class<? extends PageObjectView<? extends Shape>> viewClass) {
|
||||
Class<? extends PageObjectView<? extends Shape>> viewClass) {
|
||||
PageObjectView<Shape> objectView = (PageObjectView<Shape>) viewFactory.getInstance(viewClass);
|
||||
objectView.setPageShape(shape);
|
||||
objectView.setOnClose(() -> {
|
||||
|
@ -1032,6 +1218,10 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
return getPresenterConfig().getExternalNotesConfig();
|
||||
}
|
||||
|
||||
private ExternalWindowConfiguration getExternalSlideNotesConfig() {
|
||||
return getPresenterConfig().getExternalSlideNotesConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
stylusHandler = new StylusHandler(toolController, () -> {
|
||||
|
@ -1151,6 +1341,12 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
initExternalScreenBehavior(getExternalNotesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalNotesViewEvent(enabled, show)));
|
||||
|
||||
view.setOnExternalSlideNotesPositionChanged(this::externalSlideNotesPositionChanged);
|
||||
view.setOnExternalSlideNotesSizeChanged(this::externalSlideNotesSizeChanged);
|
||||
view.setOnExternalSlideNotesClosed(this::externalSlideNotesClosed);
|
||||
initExternalScreenBehavior(getExternalSlideNotesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalSlideNotesViewEvent(enabled, show)));
|
||||
|
||||
view.setPageRenderer(renderController);
|
||||
view.setExtendedFullscreen(config.getExtendedFullscreen());
|
||||
view.setMessengerState(ExecutableState.Stopped);
|
||||
|
@ -1179,30 +1375,50 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
view.setOnStopPeerConnection(streamService::stopPeerConnection);
|
||||
|
||||
// Register shortcuts that are associated with the SlideView.
|
||||
registerShortcut(Shortcut.SLIDE_FIRST, this::firstPage);
|
||||
registerShortcut(Shortcut.SLIDE_LAST, this::lastPage);
|
||||
|
||||
registerShortcut(Shortcut.SLIDE_NEXT_DOWN, this::nextPage);
|
||||
registerShortcut(Shortcut.SLIDE_NEXT_PAGE_DOWN, this::nextPage);
|
||||
registerShortcut(Shortcut.SLIDE_NEXT_RIGHT, this::nextPage);
|
||||
registerShortcut(Shortcut.SLIDE_NEXT_SPACE, this::nextPage);
|
||||
registerShortcut(Shortcut.SLIDE_NEXT_10, this::tenPagesForward);
|
||||
|
||||
registerShortcut(Shortcut.SLIDE_PREVIOUS_LEFT, this::previousPage);
|
||||
registerShortcut(Shortcut.SLIDE_PREVIOUS_PAGE_UP, this::previousPage);
|
||||
registerShortcut(Shortcut.SLIDE_PREVIOUS_UP, this::previousPage);
|
||||
registerShortcut(Shortcut.SLIDE_PREVIOUS_BACK_SPACE, this::previousPage);
|
||||
registerShortcut(Shortcut.SLIDE_PREVIOUS_10, this::tenPagesBack);
|
||||
|
||||
registerShortcut(Shortcut.SLIDE_OVERLAY_START, this::overlayStart);
|
||||
registerShortcut(Shortcut.SLIDE_OVERLAY_END, this::overlayEnd);
|
||||
registerShortcut(Shortcut.SLIDE_OVERLAY_PREVIOUS, this::overlayPreviousPage);
|
||||
registerShortcut(Shortcut.SLIDE_OVERLAY_NEXT, this::overlayNextPage);
|
||||
|
||||
registerShortcut(Shortcut.BOOKMARK_SLIDE, this::bookmarkSlide);
|
||||
registerShortcut(Shortcut.BOOKMARK_GOTO_LAST, this::bookmarkGotoLastSlide);
|
||||
|
||||
registerShortcut(Shortcut.TIMER_START, this::timerStart);
|
||||
registerShortcut(Shortcut.TIMER_PAUSE, this::timerPause);
|
||||
registerShortcut(Shortcut.TIMER_RESET, this::timerReset);
|
||||
|
||||
registerShortcut(Shortcut.COPY_OVERLAY, this::copyOverlay);
|
||||
registerShortcut(Shortcut.COPY_OVERLAY_NEXT_PAGE_CTRL, this::copyNextOverlay);
|
||||
registerShortcut(Shortcut.COPY_OVERLAY_NEXT_PAGE_SHIFT, this::copyNextOverlay);
|
||||
|
||||
view.setMessageBarPosition(getPresenterConfig()
|
||||
.getSlideViewConfiguration().getMessageBarPosition());
|
||||
|
||||
view.setNotesBarPosition(getPresenterConfig()
|
||||
.getSlideViewConfiguration().getNotesBarPosition());
|
||||
view.setNotesPosition(getPresenterConfig()
|
||||
.getSlideViewConfiguration().getSlideNotesPosition());
|
||||
|
||||
view.setNoteSlidePosition(getPresenterConfig()
|
||||
.getSlideViewConfiguration().getNoteSlidePosition());
|
||||
|
||||
view.setParticipantsPosition(getPresenterConfig()
|
||||
.getSlideViewConfiguration().getParticipantsPosition());
|
||||
|
||||
view.setPreviewPosition(getPresenterConfig()
|
||||
.getSlideViewConfiguration().getPreviewPosition());
|
||||
.getSlideViewConfiguration().getSlidePreviewPosition());
|
||||
|
||||
try {
|
||||
recordingService.init();
|
||||
|
@ -1240,16 +1456,32 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
}
|
||||
|
||||
private void showExternalScreens() {
|
||||
showExternalScreen(getExternalMessagesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalMessagesViewEvent(enabled, show)));
|
||||
showExternalScreen(getExternalParticipantsConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalParticipantsViewEvent(enabled, show)));
|
||||
showExternalScreen(getExternalSlidePreviewConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalSlidePreviewViewEvent(enabled, show)));
|
||||
showExternalScreen(getExternalSpeechConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalSpeechViewEvent(enabled, show)));
|
||||
showExternalScreen(getExternalNotesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalNotesViewEvent(enabled, show)));
|
||||
SlideViewConfiguration viewConfig = getPresenterConfig().getSlideViewConfiguration();
|
||||
|
||||
if (viewConfig.getMessageBarPosition() == MessageBarPosition.EXTERNAL) {
|
||||
showExternalScreen(getExternalMessagesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalMessagesViewEvent(enabled, show)));
|
||||
}
|
||||
if (viewConfig.getParticipantsPosition() == ParticipantsPosition.EXTERNAL) {
|
||||
showExternalScreen(getExternalParticipantsConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalParticipantsViewEvent(enabled, show)));
|
||||
}
|
||||
if (viewConfig.getSlidePreviewPosition() == SlidePreviewPosition.EXTERNAL) {
|
||||
showExternalScreen(getExternalSlidePreviewConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalSlidePreviewViewEvent(enabled, show)));
|
||||
}
|
||||
if (viewConfig.getSpeechPosition() == SpeechPosition.EXTERNAL) {
|
||||
showExternalScreen(getExternalSpeechConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalSpeechViewEvent(enabled, show)));
|
||||
}
|
||||
if (viewConfig.getSlideNotesPosition() == SlideNotesPosition.EXTERNAL) {
|
||||
showExternalScreen(getExternalNotesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalNotesViewEvent(enabled, show)));
|
||||
}
|
||||
if (viewConfig.getNoteSlidePosition() == NoteSlidePosition.EXTERNAL) {
|
||||
showExternalScreen(getExternalSlideNotesConfig(),
|
||||
(enabled, show) -> eventBus.post(new ExternalSlideNotesViewEvent(enabled, show)));
|
||||
}
|
||||
}
|
||||
|
||||
private void showExternalScreen(ExternalWindowConfiguration config, BiConsumer<Boolean, Boolean> action) {
|
||||
|
@ -1279,9 +1511,6 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
if (persistent) {
|
||||
config.setEnabled(false);
|
||||
config.setScreen(null);
|
||||
config.setPosition(null);
|
||||
config.setSize(null);
|
||||
}
|
||||
|
||||
view.hideExternalMessages();
|
||||
|
@ -1302,9 +1531,6 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
if (persistent) {
|
||||
config.setEnabled(false);
|
||||
config.setScreen(null);
|
||||
config.setPosition(null);
|
||||
config.setSize(null);
|
||||
}
|
||||
|
||||
view.hideExternalParticipants();
|
||||
|
@ -1325,9 +1551,6 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
if (persistent) {
|
||||
config.setEnabled(false);
|
||||
config.setScreen(null);
|
||||
config.setPosition(null);
|
||||
config.setSize(null);
|
||||
}
|
||||
|
||||
view.hideExternalSlidePreview();
|
||||
|
@ -1348,9 +1571,6 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
if (persistent) {
|
||||
config.setEnabled(false);
|
||||
config.setScreen(null);
|
||||
config.setPosition(null);
|
||||
config.setSize(null);
|
||||
}
|
||||
|
||||
view.hideExternalSpeech();
|
||||
|
@ -1371,14 +1591,30 @@ public class SlidesPresenter extends Presenter<SlidesView> {
|
|||
|
||||
if (persistent) {
|
||||
config.setEnabled(false);
|
||||
config.setScreen(null);
|
||||
config.setPosition(null);
|
||||
config.setSize(null);
|
||||
}
|
||||
|
||||
view.hideExternalNotes();
|
||||
}
|
||||
|
||||
private void viewShowExternalSlideNotes(boolean persistent) {
|
||||
final ExternalWindowConfiguration config = getExternalSlideNotesConfig();
|
||||
|
||||
if (persistent) {
|
||||
config.setEnabled(true);
|
||||
}
|
||||
|
||||
view.showExternalSlideNotes(config.getScreen(), config.getPosition(), config.getSize());
|
||||
}
|
||||
|
||||
private void viewHideExternalSlideNotes(boolean persistent) {
|
||||
final ExternalWindowConfiguration config = getExternalSlideNotesConfig();
|
||||
|
||||
if (persistent) {
|
||||
config.setEnabled(false);
|
||||
}
|
||||
|
||||
view.hideExternalSlideNotes();
|
||||
}
|
||||
|
||||
private boolean checkIfScreenInList(List<Screen> screens, Screen screen) {
|
||||
if (screen == null) {
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.google.common.eventbus.Subscribe;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
|
||||
|
@ -37,10 +38,7 @@ import org.lecturestudio.core.app.dictionary.Dictionary;
|
|||
import org.lecturestudio.core.audio.AudioDeviceNotConnectedException;
|
||||
import org.lecturestudio.core.audio.bus.event.TextFontEvent;
|
||||
import org.lecturestudio.core.bus.EventBus;
|
||||
import org.lecturestudio.core.bus.event.CustomizeToolbarEvent;
|
||||
import org.lecturestudio.core.bus.event.DocumentEvent;
|
||||
import org.lecturestudio.core.bus.event.PageEvent;
|
||||
import org.lecturestudio.core.bus.event.ToolSelectionEvent;
|
||||
import org.lecturestudio.core.bus.event.*;
|
||||
import org.lecturestudio.core.controller.PresentationController;
|
||||
import org.lecturestudio.core.controller.ToolController;
|
||||
import org.lecturestudio.core.graphics.Color;
|
||||
|
@ -60,6 +58,7 @@ import org.lecturestudio.core.text.TeXFont;
|
|||
import org.lecturestudio.core.tool.ColorPalette;
|
||||
import org.lecturestudio.core.tool.PaintSettings;
|
||||
import org.lecturestudio.core.tool.ToolType;
|
||||
import org.lecturestudio.core.view.NotificationType;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
import org.lecturestudio.core.view.PresentationParameterProvider;
|
||||
import org.lecturestudio.core.view.ViewType;
|
||||
|
@ -68,8 +67,10 @@ import org.lecturestudio.presenter.api.context.PresenterContext;
|
|||
import org.lecturestudio.presenter.api.event.RecordingStateEvent;
|
||||
import org.lecturestudio.presenter.api.event.ScreenShareSelectEvent;
|
||||
import org.lecturestudio.presenter.api.event.StreamingStateEvent;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
import org.lecturestudio.presenter.api.presenter.command.CloseablePresenterCommand;
|
||||
import org.lecturestudio.presenter.api.presenter.command.StartRecordingCommand;
|
||||
import org.lecturestudio.presenter.api.service.BookmarkService;
|
||||
import org.lecturestudio.presenter.api.service.RecordingService;
|
||||
import org.lecturestudio.presenter.api.view.ToolbarView;
|
||||
|
||||
|
@ -86,6 +87,9 @@ public class ToolbarPresenter extends Presenter<ToolbarView> {
|
|||
@Inject
|
||||
private ToolController toolController;
|
||||
|
||||
@Inject
|
||||
private BookmarkService bookmarkService;
|
||||
|
||||
@Inject
|
||||
private PresentationController presentationController;
|
||||
|
||||
|
@ -138,7 +142,28 @@ public class ToolbarPresenter extends Presenter<ToolbarView> {
|
|||
|
||||
page.addPageEditedListener(pageEditedListener);
|
||||
|
||||
boolean hasBookmark = false;
|
||||
for(Bookmark bookmark : bookmarkService.getBookmarks().getAllBookmarks()){
|
||||
if(bookmark.getPage().equals(page)){
|
||||
hasBookmark = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
view.selectNewBookmarkButton(hasBookmark);
|
||||
pageChanged(page);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(final BookmarkEvent event){
|
||||
if(event.getPage().equals(documentService.getDocuments().getSelectedDocument().getCurrentPage())){
|
||||
switch (event.getType()){
|
||||
case CREATED -> view.selectNewBookmarkButton(true);
|
||||
case REMOVED -> view.selectNewBookmarkButton(false);
|
||||
default -> view.selectNewBookmarkButton(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -476,6 +501,69 @@ public class ToolbarPresenter extends Presenter<ToolbarView> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Select the previous bookmark in the bookmark list.
|
||||
*/
|
||||
public void selectPreviousBookmark() {
|
||||
Page page = bookmarkService.getPrevBookmarkPage();
|
||||
if (nonNull(page)) {
|
||||
documentService.selectPage(page);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the next bookmark in the bookmark list.
|
||||
*/
|
||||
public void selectNextBookmark() {
|
||||
Page page = bookmarkService.getNextBookmarkPage();
|
||||
if (nonNull(page)) {
|
||||
documentService.selectPage(page);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new default bookmark.
|
||||
*/
|
||||
private void createNewBookmark() {
|
||||
try {
|
||||
Bookmark currBookmark = bookmarkService.getPageBookmark();
|
||||
if (nonNull(currBookmark)) {
|
||||
String shortcut = currBookmark.getShortcut();
|
||||
bookmarkService.deleteBookmark(currBookmark);
|
||||
bookmarkRemoved(shortcut);
|
||||
view.selectNewBookmarkButton(false);
|
||||
}
|
||||
else {
|
||||
bookmarkCreated(bookmarkService.createDefaultBookmark());
|
||||
view.selectNewBookmarkButton(true);
|
||||
}
|
||||
}
|
||||
catch (BookmarkExistsException e) {
|
||||
Page page = documentService.getDocuments().getSelectedDocument().getCurrentPage();
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.exists"), page.getPageNumber());
|
||||
context.showNotification(NotificationType.WARNING, "bookmark.assign.warning", message);
|
||||
}
|
||||
catch (BookmarkException e) {
|
||||
handleException(e, "Create bookmark failed", "bookmark.assign.warning");
|
||||
}
|
||||
}
|
||||
private void bookmarkCreated(Bookmark bookmark) {
|
||||
String shortcut = bookmark.getShortcut().toUpperCase();
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.created"), shortcut);
|
||||
|
||||
context.showNotificationPopup(message);
|
||||
close();
|
||||
}
|
||||
|
||||
private void bookmarkRemoved(String shortcut) {
|
||||
String message = MessageFormat.format(context.getDictionary().get("bookmark.removed"), shortcut);
|
||||
|
||||
context.showNotificationPopup(message);
|
||||
close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
PresenterContext presenterContext = (PresenterContext) context;
|
||||
|
@ -494,6 +582,11 @@ public class ToolbarPresenter extends Presenter<ToolbarView> {
|
|||
view.setOnPreviousSlide(toolController::selectPreviousPage);
|
||||
view.setOnNextSlide(toolController::selectNextPage);
|
||||
|
||||
view.setOnPreviousBookmark(this::selectPreviousBookmark);
|
||||
view.setOnNextBookmark(this::selectNextBookmark);
|
||||
|
||||
view.setOnNewBookmark(this::createNewBookmark);
|
||||
|
||||
view.setOnCustomPaletteColor(this::customPaletteColor);
|
||||
view.setOnCustomColor(this::customColor);
|
||||
view.setOnColor1(this::color1);
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (C) 2020 TU Darmstadt, Department of Computer Science,
|
||||
* Embedded Systems and Applications Group.
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.lecturestudio.presenter.api.presenter.command;
|
||||
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.presenter.command.ShowPresenterCommand;
|
||||
import org.lecturestudio.presenter.api.presenter.GotoBookmarkPresenter;
|
||||
|
||||
public class GotoBookmarkCommand extends ShowPresenterCommand<GotoBookmarkPresenter> {
|
||||
|
||||
private final Document selectedDocument;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link GotoBookmarkCommand} with the corresponding presenter class.
|
||||
*
|
||||
* @param document The currently selected document.
|
||||
*/
|
||||
public GotoBookmarkCommand(Document document) {
|
||||
super(GotoBookmarkPresenter.class);
|
||||
|
||||
selectedDocument = document;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(GotoBookmarkPresenter presenter) {
|
||||
presenter.setSelectedDocument(selectedDocument);
|
||||
}
|
||||
}
|
|
@ -21,11 +21,14 @@ package org.lecturestudio.presenter.api.service;
|
|||
import static java.util.Objects.isNull;
|
||||
import static java.util.Objects.nonNull;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.lecturestudio.core.app.ApplicationContext;
|
||||
import org.lecturestudio.core.bus.event.BookmarkEvent;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.DocumentList;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
|
@ -33,6 +36,7 @@ import org.lecturestudio.core.service.DocumentService;
|
|||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkException;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkKeyException;
|
||||
import org.lecturestudio.presenter.api.model.BookmarkExistsException;
|
||||
import org.lecturestudio.presenter.api.model.Bookmarks;
|
||||
|
||||
@Singleton
|
||||
|
@ -44,10 +48,15 @@ public class BookmarkService {
|
|||
|
||||
private Page prevBookmarkPage;
|
||||
|
||||
private int defaultBookmarkCounter = 1;
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
|
||||
@Inject
|
||||
public BookmarkService(DocumentService documentService) {
|
||||
public BookmarkService(DocumentService documentService, ApplicationContext context) {
|
||||
this.documentService = documentService;
|
||||
this.context = context;
|
||||
this.bookmarks = new Bookmarks();
|
||||
}
|
||||
|
||||
|
@ -57,11 +66,12 @@ public class BookmarkService {
|
|||
|
||||
public void clearBookmarks() {
|
||||
Document selectedDoc = documentService.getDocuments().getSelectedDocument();
|
||||
|
||||
context.getEventBus().post(new BookmarkEvent(documentService.getDocuments().getSelectedDocument().getCurrentPage(), BookmarkEvent.Type.REMOVED));
|
||||
bookmarks.clear(selectedDoc);
|
||||
}
|
||||
|
||||
public void clearBookmarks(Document document) {
|
||||
context.getEventBus().post(new BookmarkEvent(documentService.getDocuments().getSelectedDocument().getCurrentPage(), BookmarkEvent.Type.REMOVED));
|
||||
bookmarks.clear(document);
|
||||
}
|
||||
|
||||
|
@ -81,20 +91,52 @@ public class BookmarkService {
|
|||
if (bookmark.getShortcut().equalsIgnoreCase(keyStr)) {
|
||||
throw new BookmarkKeyException("Bookmark key is already assigned to another bookmark");
|
||||
}
|
||||
if (bookmark.getPage().equals(page)){
|
||||
throw new BookmarkExistsException("Page is already bookmarked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Bookmark bookmark = new Bookmark(keyStr, page);
|
||||
|
||||
bookmarks.add(bookmark);
|
||||
|
||||
context.getEventBus().post(new BookmarkEvent(page, BookmarkEvent.Type.CREATED));
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
public void deleteBookmark(Bookmark bookmark) throws BookmarkException {
|
||||
context.getEventBus().post(new BookmarkEvent(bookmark.getPage(), BookmarkEvent.Type.REMOVED));
|
||||
bookmarks.removeBookmark(bookmark);
|
||||
}
|
||||
|
||||
public Bookmark getPageBookmark() throws BookmarkException {
|
||||
Document selectedDoc = documentService.getDocuments().getSelectedDocument();
|
||||
Page page = selectedDoc.getCurrentPage();
|
||||
if (isNull(page)) {
|
||||
throw new BookmarkException("No document selected");
|
||||
}
|
||||
|
||||
List<Bookmark> docBookmarks = bookmarks.getDocumentBookmarks(selectedDoc);
|
||||
|
||||
if (nonNull(docBookmarks)) {
|
||||
for (Bookmark bookmark : docBookmarks) {
|
||||
if(bookmark.getPage().equals(page)){
|
||||
return bookmark;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasBookmark(Bookmark bookmark) {
|
||||
if (isNull(bookmark)) {
|
||||
throw new NullPointerException("No bookmark provided");
|
||||
}
|
||||
|
||||
Bookmark selectedBookmark = bookmarks.getBookmark(bookmark.getShortcut());
|
||||
|
||||
return nonNull(selectedBookmark);
|
||||
}
|
||||
|
||||
public void gotoBookmark(Bookmark bookmark) throws BookmarkException {
|
||||
if (isNull(bookmark)) {
|
||||
throw new NullPointerException("No bookmark provided");
|
||||
|
@ -138,4 +180,98 @@ public class BookmarkService {
|
|||
documentService.selectPage(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bookmark with a default shortcut
|
||||
*
|
||||
* @return the new created bookmark
|
||||
*/
|
||||
public Bookmark createDefaultBookmark() throws BookmarkException{
|
||||
Bookmark bookmark = createBookmark("L" + defaultBookmarkCounter);
|
||||
|
||||
defaultBookmarkCounter++;
|
||||
return bookmark;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the next bookmark where the pagenumber is lower than current pagenumber.
|
||||
*
|
||||
* @return Page with bookmark with the next lower pagenumber
|
||||
*/
|
||||
public Page getPrevBookmarkPage(){
|
||||
Document currDoc = documentService.getDocuments().getSelectedDocument();
|
||||
List<Bookmark> allDocBookmarks = bookmarks.getDocumentBookmarks(currDoc);
|
||||
if(!nonNull(allDocBookmarks)){
|
||||
return null;
|
||||
}
|
||||
Bookmark currBookmark = getBookmarkCurrentPage(allDocBookmarks);
|
||||
|
||||
if(!nonNull(currBookmark)){
|
||||
createDefaultBookmarkCurrentPage();
|
||||
currBookmark = getBookmarks().getBookmark("L0");
|
||||
}
|
||||
|
||||
int maxBookmarks = allDocBookmarks.size();
|
||||
|
||||
allDocBookmarks.sort(Comparator.comparingInt(a -> a.getPage().getPageNumber()));
|
||||
int bookmarkPos = allDocBookmarks.indexOf(currBookmark);
|
||||
|
||||
if(maxBookmarks == 0 || bookmarkPos == 0){
|
||||
return null;
|
||||
}
|
||||
bookmarkPos--;
|
||||
Bookmark bookmark = allDocBookmarks.get(bookmarkPos);
|
||||
return bookmark.getPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the next bookmark where the pagenumber is higher than current pagenumber.
|
||||
*
|
||||
* @return Page with bookmark with the next higher pagenumber
|
||||
*/
|
||||
public Page getNextBookmarkPage(){
|
||||
Document currDoc = documentService.getDocuments().getSelectedDocument();
|
||||
List<Bookmark> allDocBookmarks = bookmarks.getDocumentBookmarks(currDoc);
|
||||
if(!nonNull(allDocBookmarks)){
|
||||
return null;
|
||||
}
|
||||
Bookmark currBookmark = getBookmarkCurrentPage(allDocBookmarks);
|
||||
|
||||
if(!nonNull(currBookmark)){
|
||||
createDefaultBookmarkCurrentPage();
|
||||
currBookmark = getBookmarks().getBookmark("L0");
|
||||
}
|
||||
|
||||
int maxBookmarks = allDocBookmarks.size();
|
||||
|
||||
allDocBookmarks.sort(Comparator.comparingInt(a -> a.getPage().getPageNumber()));
|
||||
int bookmarkPos = allDocBookmarks.indexOf(currBookmark);
|
||||
if(bookmarkPos + 1 == maxBookmarks){
|
||||
return null;
|
||||
}
|
||||
bookmarkPos++;
|
||||
Bookmark bookmark = allDocBookmarks.get(bookmarkPos);
|
||||
return bookmark.getPage();
|
||||
}
|
||||
|
||||
private Bookmark getBookmarkCurrentPage(List<Bookmark> allDocBookmarks){
|
||||
Page currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage();
|
||||
for(Bookmark bm : allDocBookmarks){
|
||||
if(bm.getPage().equals(currPage)){
|
||||
return bm;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Bookmark createDefaultBookmarkCurrentPage(){
|
||||
try {
|
||||
if (nonNull(getBookmarks().getBookmark("L0"))) {
|
||||
deleteBookmark(getBookmarks().getBookmark("L0"));
|
||||
}
|
||||
return createBookmark("L0");
|
||||
} catch (BookmarkException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.lecturestudio.presenter.api.view;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.view.Action;
|
||||
import org.lecturestudio.core.view.ConsumerAction;
|
||||
import org.lecturestudio.core.view.View;
|
||||
|
@ -27,12 +28,16 @@ import org.lecturestudio.presenter.api.model.Bookmark;
|
|||
|
||||
public interface GotoBookmarkView extends View {
|
||||
|
||||
void setDocument(Document document);
|
||||
|
||||
void setBookmarks(List<Bookmark> bookmarkList);
|
||||
|
||||
void removeBookmark(Bookmark bookmark);
|
||||
|
||||
void setOnClose(Action action);
|
||||
|
||||
void setOnGotoPageNumber(ConsumerAction<Integer> action);
|
||||
|
||||
void setOnDeleteBookmark(ConsumerAction<Bookmark> action);
|
||||
|
||||
void setOnGotoBookmark(ConsumerAction<Bookmark> action);
|
||||
|
|
|
@ -26,18 +26,13 @@ import org.lecturestudio.core.ExecutableState;
|
|||
import org.lecturestudio.core.beans.BooleanProperty;
|
||||
import org.lecturestudio.core.beans.IntegerProperty;
|
||||
import org.lecturestudio.core.beans.ObjectProperty;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.model.RecentDocument;
|
||||
import org.lecturestudio.core.model.Time;
|
||||
import org.lecturestudio.core.model.*;
|
||||
import org.lecturestudio.core.view.Action;
|
||||
import org.lecturestudio.core.view.ConsumerAction;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
import org.lecturestudio.core.view.View;
|
||||
import org.lecturestudio.presenter.api.context.PresenterContext.ParticipantCount;
|
||||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
import org.lecturestudio.presenter.api.model.Bookmarks;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
import org.lecturestudio.presenter.api.service.QuizWebServiceState;
|
||||
|
||||
public interface MenuView extends View {
|
||||
|
@ -78,64 +73,33 @@ public interface MenuView extends View {
|
|||
|
||||
void bindShowOutline(BooleanProperty showProperty);
|
||||
|
||||
void setAdvancedSettings(boolean selected);
|
||||
|
||||
void bindFullscreen(BooleanProperty fullscreen);
|
||||
|
||||
void setOnAdvancedSettings(ConsumerAction<Boolean> action);
|
||||
|
||||
void setOnCustomizeToolbar(Action action);
|
||||
|
||||
void setExternalMessages(boolean selected, boolean show);
|
||||
void setSpeechPosition(SpeechPosition position);
|
||||
|
||||
void setOnExternalMessages(ConsumerAction<Boolean> action);
|
||||
void setOnSpeechPosition(ConsumerAction<SpeechPosition> action);
|
||||
|
||||
void setExternalParticipants(boolean selected, boolean show);
|
||||
void setMessagesPosition(MessageBarPosition position);
|
||||
|
||||
void setOnExternalParticipants(ConsumerAction<Boolean> action);
|
||||
void setOnMessagesPosition(ConsumerAction<MessageBarPosition> action);
|
||||
|
||||
void setExternalSlidePreview(boolean selected, boolean show);
|
||||
void setSlideNotesPosition(SlideNotesPosition position);
|
||||
|
||||
void setOnExternalSlidePreview(ConsumerAction<Boolean> action);
|
||||
void setOnSlideNotesPosition(ConsumerAction<SlideNotesPosition> action);
|
||||
|
||||
void setExternalSpeech(boolean selected, boolean show);
|
||||
void setNoteSlidePosition(NoteSlidePosition position);
|
||||
|
||||
void setOnExternalSpeech(ConsumerAction<Boolean> action);
|
||||
void setOnNoteSlidePosition(ConsumerAction<NoteSlidePosition> action);
|
||||
|
||||
void setExternalNotes(boolean selected, boolean show);
|
||||
void setParticipantsPosition(ParticipantsPosition position);
|
||||
|
||||
void setOnExternalNotes(ConsumerAction<Boolean> action);
|
||||
void setOnParticipantsPosition(ConsumerAction<ParticipantsPosition> action);
|
||||
|
||||
void setOnMessagesPositionLeft(Action action);
|
||||
void setSlidePreviewPosition(SlidePreviewPosition position);
|
||||
|
||||
void setMessagesPositionLeft();
|
||||
|
||||
void setOnMessagesPositionBottom(Action action);
|
||||
|
||||
void setMessagesPositionBottom();
|
||||
|
||||
void setOnMessagesPositionRight(Action action);
|
||||
|
||||
void setMessagesPositionRight();
|
||||
|
||||
void setOnNotesPositionLeft(Action action);
|
||||
|
||||
void setNotesPositionLeft();
|
||||
|
||||
void setOnNotesPositionBottom(Action action);
|
||||
|
||||
void setNotesPositionBottom();
|
||||
|
||||
|
||||
void setOnParticipantsPositionLeft(Action action);
|
||||
|
||||
void setParticipantsPositionLeft();
|
||||
|
||||
void setOnParticipantsPositionRight(Action action);
|
||||
|
||||
void setParticipantsPositionRight();
|
||||
|
||||
void bindPreviewPosition(ObjectProperty<MessageBarPosition> position);
|
||||
void setOnSlidePreviewPosition(ConsumerAction<SlidePreviewPosition> action);
|
||||
|
||||
/**
|
||||
* Whiteboard Menu
|
||||
|
@ -209,10 +173,18 @@ public interface MenuView extends View {
|
|||
|
||||
void setOnShowNewBookmarkView(Action action);
|
||||
|
||||
void setOnCreateNewDefaultBookmarkView(Action action);
|
||||
|
||||
void setOnRemoveBookmarkView(Action action);
|
||||
|
||||
void setOnShowGotoBookmarkView(Action action);
|
||||
|
||||
void setOnPreviousBookmark(Action action);
|
||||
|
||||
void setOnPrevBookmark(Action action);
|
||||
|
||||
void setOnNextBookmark(Action action);
|
||||
|
||||
void setOnOpenBookmark(ConsumerAction<Bookmark> action);
|
||||
|
||||
/**
|
||||
|
@ -250,4 +222,13 @@ public interface MenuView extends View {
|
|||
void bindCourseParticipantsCount(ObjectProperty<ParticipantCount> count);
|
||||
|
||||
void setQuizServiceState(QuizWebServiceState state);
|
||||
|
||||
/**
|
||||
* Split notes
|
||||
*/
|
||||
|
||||
void setSplitNotesPosition(NotesPosition position);
|
||||
|
||||
void setOnSplitNotesPosition(ConsumerAction<NotesPosition> action);
|
||||
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ import org.lecturestudio.core.model.DocumentOutline;
|
|||
import org.lecturestudio.core.model.DocumentOutlineItem;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.view.*;
|
||||
import org.lecturestudio.presenter.api.model.NoteBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
import org.lecturestudio.presenter.api.config.SlideViewConfiguration;
|
||||
import org.lecturestudio.swing.model.ExternalWindowPosition;
|
||||
import org.lecturestudio.core.stylus.StylusHandler;
|
||||
|
@ -73,6 +72,8 @@ public interface SlidesView extends View {
|
|||
|
||||
void setPage(Page page, PresentationParameter parameter);
|
||||
|
||||
void setSlideNotes(Page page, PresentationParameter parameter);
|
||||
|
||||
void setPageRenderer(RenderController pageRenderer);
|
||||
|
||||
void setOutline(DocumentOutline outline);
|
||||
|
@ -175,6 +176,12 @@ public interface SlidesView extends View {
|
|||
|
||||
void setOnExternalNotesClosed(Action action);
|
||||
|
||||
void setOnExternalSlideNotesPositionChanged(ConsumerAction<ExternalWindowPosition> action);
|
||||
|
||||
void setOnExternalSlideNotesSizeChanged(ConsumerAction<Dimension> action);
|
||||
|
||||
void setOnExternalSlideNotesClosed(Action action);
|
||||
|
||||
void showExternalMessages(Screen screen, Point position, Dimension size);
|
||||
|
||||
void hideExternalMessages();
|
||||
|
@ -195,12 +202,18 @@ public interface SlidesView extends View {
|
|||
|
||||
void hideExternalNotes();
|
||||
|
||||
void showExternalSlideNotes(Screen screen, Point position, Dimension size);
|
||||
|
||||
void hideExternalSlideNotes();
|
||||
|
||||
void setMessageBarPosition(MessageBarPosition position);
|
||||
|
||||
void setNotesBarPosition(NoteBarPosition position);
|
||||
void setNotesPosition(SlideNotesPosition position);
|
||||
|
||||
void setParticipantsPosition(MessageBarPosition position);
|
||||
void setNoteSlidePosition(NoteSlidePosition position);
|
||||
|
||||
void setPreviewPosition(MessageBarPosition position);
|
||||
void setParticipantsPosition(ParticipantsPosition position);
|
||||
|
||||
void setPreviewPosition(SlidePreviewPosition position);
|
||||
|
||||
}
|
||||
|
|
|
@ -56,6 +56,12 @@ public interface ToolbarView extends View {
|
|||
|
||||
void setOnNextSlide(Action action);
|
||||
|
||||
void setOnPreviousBookmark(Action action);
|
||||
|
||||
void setOnNextBookmark(Action action);
|
||||
|
||||
void setOnNewBookmark(Action action);
|
||||
|
||||
void setOnCustomPaletteColor(ConsumerAction<Color> action);
|
||||
|
||||
void setOnCustomColor(Action action);
|
||||
|
@ -122,6 +128,8 @@ public interface ToolbarView extends View {
|
|||
|
||||
void selectColorButton(ToolType toolType, PaintSettings settings);
|
||||
|
||||
void selectNewBookmarkButton(boolean hasBookmark);
|
||||
|
||||
void selectToolButton(ToolType toolType);
|
||||
|
||||
void openCustomizeToolbarDialog();
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
audio.device.connected = Audiogerät verbunden
|
||||
audio.device.disconnected = Audiogerät getrennt
|
||||
audio.device.connected = Audiogerät verbunden
|
||||
audio.device.disconnected = Audiogerät getrennt
|
||||
|
||||
bookmark.assign.error = Lesezeichen konnte nicht erstellt werden
|
||||
bookmark.assign.warning = Lesezeichen konnte nicht erstellt werden
|
||||
bookmark.delete.error = Lesezeichen konnte nicht gel\u00f6scht werden
|
||||
bookmark.goto.error = Lesezeichen konnte nicht angesprungen werden
|
||||
bookmark.key.exists = Ein Lesezeichen mit der Taste {0} existiert bereits
|
||||
bookmark.key.not.existing = Ein Lesezeichen mit der Taste {0} existiert nicht
|
||||
bookmark.key.exists = Ein Lesezeichen mit der Taste {0} existiert bereits.
|
||||
bookmark.exists = Ein Lesezeichen existiert bereits f\u00fcr die aktuelle Folie.
|
||||
bookmark.key.not.existing = Ein Lesezeichen mit der Taste {0} existiert nicht.
|
||||
bookmark.created = Neues Lesezeichen erstellt: {0}
|
||||
bookmark.removed = Lesezeichen gel\u00f6scht: {0}
|
||||
|
||||
document.save.error = Dokument konnte nicht gespeichert werden
|
||||
document.save.lecture = Vorlesung
|
||||
|
@ -65,6 +67,7 @@ message.slide.create.error = Nachrichtenfolie konnte nicht erstellt werden
|
|||
|
||||
service.timeout.error = Der Dienst ist derzeit nicht verf\u00fcgbar. Sollte der Fehler dauerhaft auftreten, so wenden Sie sich bitte an den Administrator ihres Vertrauens.
|
||||
|
||||
open.document = Dokument wird geladen
|
||||
open.document.error = Dokument konnte nicht ge\u00f6ffnet werden
|
||||
open.page.file.error = Die Datei konnte nicht ge\u00f6ffnet werden
|
||||
open.page.uri.error = Der Link konnte nicht ge\u00f6ffnet werden
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
audio.device.connected = Audio device connected
|
||||
audio.device.disconnected = Audio device disconnected
|
||||
|
||||
bookmark.assign.error = Bookmark could not be created
|
||||
bookmark.assign.warning = Bookmark could not be created
|
||||
bookmark.delete.error = Bookmark could not be deleted
|
||||
bookmark.goto.error = Bookmark could not be opened
|
||||
bookmark.key.exists = A bookmark with the key {0} already exists
|
||||
bookmark.key.not.existing = A bookmark with the key {0} does not exist
|
||||
bookmark.key.exists = A bookmark with the key {0} already exists.
|
||||
bookmark.exists = A bookmark already exists for the current slide.
|
||||
bookmark.key.not.existing = A bookmark with the key {0} does not exist.
|
||||
bookmark.created = New bookmark created: {0}
|
||||
bookmark.removed = Bookmark removed: {0}
|
||||
|
||||
document.save.error = Document could not be saved
|
||||
document.save.lecture = Lecture
|
||||
|
@ -65,6 +67,7 @@ message.slide.create.error = Message slide could not be created
|
|||
|
||||
service.timeout.error = The service is currently not available. If the error occurs permanently, please contact your trusted administrator.
|
||||
|
||||
open.document = loading document
|
||||
open.document.error = Document could not be opened
|
||||
open.page.file.error = The file could not be opened
|
||||
open.page.uri.error = The link could not be opened
|
||||
|
|
|
@ -44,17 +44,19 @@ class CreateBookmarkPresenterTest extends PresenterTest {
|
|||
|
||||
private BookmarkService bookmarkService;
|
||||
|
||||
private DocumentService documentService;
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws IOException {
|
||||
Document document = new Document();
|
||||
document.createPage();
|
||||
document.createPage();
|
||||
|
||||
DocumentService documentService = new DocumentService(context);
|
||||
documentService = new DocumentService(context);
|
||||
documentService.addDocument(document);
|
||||
documentService.selectDocument(document);
|
||||
|
||||
bookmarkService = new BookmarkService(documentService);
|
||||
bookmarkService = new BookmarkService(documentService, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -74,6 +76,9 @@ class CreateBookmarkPresenterTest extends PresenterTest {
|
|||
@Test
|
||||
void testBookmarkList() throws BookmarkException {
|
||||
Bookmark a = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark z = bookmarkService.createBookmark("z");
|
||||
|
||||
CreateBookmarkMockView view = new CreateBookmarkMockView() {
|
||||
|
@ -91,6 +96,29 @@ class CreateBookmarkPresenterTest extends PresenterTest {
|
|||
presenter.initialize();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultBookmarkList() throws BookmarkException {
|
||||
Bookmark l1 = bookmarkService.createDefaultBookmark();
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark l2 = bookmarkService.createDefaultBookmark();
|
||||
|
||||
CreateBookmarkMockView view = new CreateBookmarkMockView() {
|
||||
@Override
|
||||
public void setBookmarks(List<Bookmark> bookmarkList) {
|
||||
assertNotNull(bookmarkList);
|
||||
assertFalse(bookmarkList.isEmpty());
|
||||
assertEquals(2, bookmarkList.size());
|
||||
assertEquals(l1, bookmarkList.get(0));
|
||||
assertEquals(l2, bookmarkList.get(1));
|
||||
}
|
||||
};
|
||||
|
||||
CreateBookmarkPresenter presenter = new CreateBookmarkPresenter(context, view, bookmarkService);
|
||||
presenter.initialize();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateBookmark() {
|
||||
AtomicBoolean close = new AtomicBoolean(false);
|
||||
|
@ -130,13 +158,41 @@ class CreateBookmarkPresenterTest extends PresenterTest {
|
|||
assertFalse(close.get());
|
||||
assertNotNull(notifyView);
|
||||
assertEquals(NotificationType.ERROR, notifyView.type);
|
||||
assertEquals("bookmark.assign.error", notifyView.title);
|
||||
assertEquals("bookmark.assign.warning", notifyView.title);
|
||||
assertEquals("bookmark.key.exists", notifyView.message);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateInvalidBookmarkSamePage() throws BookmarkException {
|
||||
bookmarkService.createBookmark("a");
|
||||
|
||||
AtomicBoolean close = new AtomicBoolean(false);
|
||||
|
||||
CreateBookmarkMockView view = new CreateBookmarkMockView();
|
||||
|
||||
CreateBookmarkPresenter presenter = new CreateBookmarkPresenter(context, view, bookmarkService);
|
||||
presenter.initialize();
|
||||
presenter.setOnClose(() -> {
|
||||
close.set(true);
|
||||
});
|
||||
|
||||
view.createAction.execute("z");
|
||||
|
||||
NotificationMockView notifyView = notifyViewRef.get();
|
||||
|
||||
assertFalse(close.get());
|
||||
assertNotNull(notifyView);
|
||||
assertEquals(NotificationType.ERROR, notifyView.type);
|
||||
assertEquals("bookmark.assign.warning", notifyView.title);
|
||||
assertEquals("bookmark.exists", notifyView.message);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteBookmark() throws BookmarkException {
|
||||
Bookmark a = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark z = bookmarkService.createBookmark("z");
|
||||
|
||||
CreateBookmarkMockView view = new CreateBookmarkMockView() {
|
||||
|
@ -161,6 +217,35 @@ class CreateBookmarkPresenterTest extends PresenterTest {
|
|||
assertEquals(0, bookmarkService.getBookmarks().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteDefaultBookmark() throws BookmarkException {
|
||||
Bookmark l1 = bookmarkService.createDefaultBookmark();
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark l2 = bookmarkService.createDefaultBookmark();
|
||||
|
||||
CreateBookmarkMockView view = new CreateBookmarkMockView() {
|
||||
@Override
|
||||
public void removeBookmark(Bookmark bookmark) {
|
||||
if (bookmarkService.getBookmarks().size() == 1) {
|
||||
assertEquals(l1, bookmark);
|
||||
}
|
||||
else {
|
||||
assertEquals(l2, bookmark);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CreateBookmarkPresenter presenter = new CreateBookmarkPresenter(context, view, bookmarkService);
|
||||
presenter.initialize();
|
||||
|
||||
view.deleteAction.execute(l1);
|
||||
assertEquals(1, bookmarkService.getBookmarks().size());
|
||||
|
||||
view.deleteAction.execute(l2);
|
||||
assertEquals(0, bookmarkService.getBookmarks().size());
|
||||
}
|
||||
|
||||
|
||||
private static class CreateBookmarkMockView implements CreateBookmarkView {
|
||||
|
|
|
@ -44,17 +44,20 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
|
||||
private BookmarkService bookmarkService;
|
||||
|
||||
private DocumentService documentService;
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws IOException {
|
||||
Document document = new Document();
|
||||
document.createPage();
|
||||
document.createPage();
|
||||
document.createPage();
|
||||
|
||||
DocumentService documentService = new DocumentService(context);
|
||||
documentService = new DocumentService(context);
|
||||
documentService.addDocument(document);
|
||||
documentService.selectDocument(document);
|
||||
|
||||
bookmarkService = new BookmarkService(documentService);
|
||||
bookmarkService = new BookmarkService(documentService, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -67,13 +70,16 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
}
|
||||
};
|
||||
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, bookmarkService);
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, documentService, bookmarkService);
|
||||
presenter.initialize();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBookmarkList() throws BookmarkException {
|
||||
Bookmark a = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark z = bookmarkService.createBookmark("z");
|
||||
|
||||
GotoBookmarkMockView view = new GotoBookmarkMockView() {
|
||||
|
@ -87,7 +93,7 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
}
|
||||
};
|
||||
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, bookmarkService);
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, documentService, bookmarkService);
|
||||
presenter.initialize();
|
||||
}
|
||||
|
||||
|
@ -99,7 +105,7 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
|
||||
GotoBookmarkMockView view = new GotoBookmarkMockView();
|
||||
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, bookmarkService);
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, documentService, bookmarkService);
|
||||
presenter.initialize();
|
||||
presenter.setOnClose(() -> {
|
||||
close.set(true);
|
||||
|
@ -118,7 +124,7 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
|
||||
GotoBookmarkMockView view = new GotoBookmarkMockView();
|
||||
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, bookmarkService);
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, documentService, bookmarkService);
|
||||
presenter.initialize();
|
||||
presenter.setOnClose(() -> {
|
||||
close.set(true);
|
||||
|
@ -138,6 +144,9 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
@Test
|
||||
void testDeleteBookmark() throws BookmarkException {
|
||||
Bookmark a = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark z = bookmarkService.createBookmark("z");
|
||||
|
||||
GotoBookmarkMockView view = new GotoBookmarkMockView() {
|
||||
|
@ -152,7 +161,7 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
}
|
||||
};
|
||||
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, bookmarkService);
|
||||
GotoBookmarkPresenter presenter = new GotoBookmarkPresenter(context, view, documentService, bookmarkService);
|
||||
presenter.initialize();
|
||||
|
||||
view.deleteAction.execute(a);
|
||||
|
@ -162,6 +171,32 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
assertEquals(0, bookmarkService.getBookmarks().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGoToNextBookmark() throws BookmarkException {
|
||||
Bookmark a = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark z = bookmarkService.createBookmark("z");
|
||||
currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark y = bookmarkService.createBookmark("y");
|
||||
|
||||
documentService.getDocuments().getSelectedDocument().selectPage(0);
|
||||
assertEquals(bookmarkService.getPageBookmark(), a);
|
||||
|
||||
currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
assertEquals(bookmarkService.getPageBookmark(), z);
|
||||
|
||||
currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
assertEquals(bookmarkService.getPageBookmark(), y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class GotoBookmarkMockView implements GotoBookmarkView {
|
||||
|
@ -171,6 +206,11 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
ConsumerAction<Bookmark> deleteAction;
|
||||
|
||||
|
||||
@Override
|
||||
public void setDocument(Document document) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBookmarks(List<Bookmark> bookmarkList) {
|
||||
|
||||
|
@ -186,6 +226,11 @@ class GotoBookmarkPresenterTest extends PresenterTest {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnGotoPageNumber(ConsumerAction<Integer> action) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnDeleteBookmark(ConsumerAction<Bookmark> action) {
|
||||
assertNotNull(action);
|
||||
|
|
|
@ -121,7 +121,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
|
||||
documentService = context.getDocumentService();
|
||||
|
||||
bookmarkService = new BookmarkService(documentService);
|
||||
bookmarkService = new BookmarkService(documentService, context);
|
||||
|
||||
recorder = new FileLectureRecorder(audioSystemProvider, documentService, audioConfig, getRecordingDirectory());
|
||||
|
||||
|
@ -200,7 +200,7 @@ class MainPresenterTest extends PresenterTest {
|
|||
public <T> T getInstance(Class<T> cls) {
|
||||
if (cls == SlidesPresenter.class) {
|
||||
ToolController toolController = new ToolController(context, documentService);
|
||||
return (T) new SlidesPresenter(context, createProxy(SlidesView.class), null, toolController, presentationController, null, documentService, documentRecorder, recordingService, webService, webServiceInfo, streamService);
|
||||
return (T) new SlidesPresenter(context, createProxy(SlidesView.class), null, toolController, presentationController, null, bookmarkService, documentService, documentRecorder, recordingService, webService, webServiceInfo, streamService);
|
||||
}
|
||||
else if (cls == SettingsPresenter.class) {
|
||||
return (T) new SettingsPresenter(context, createProxy(SettingsView.class));
|
||||
|
|
|
@ -39,17 +39,23 @@ class BookmarkServiceTest extends ServiceTest {
|
|||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
bookmarkService = new BookmarkService(documentService);
|
||||
bookmarkService = new BookmarkService(documentService, context);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClearBookmarks() throws BookmarkException {
|
||||
bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
bookmarkService.createBookmark("b");
|
||||
|
||||
documentService.selectDocument(document2);
|
||||
|
||||
bookmarkService.createBookmark("c");
|
||||
currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
bookmarkService.createBookmark("d");
|
||||
bookmarkService.clearBookmarks();
|
||||
|
||||
|
@ -67,12 +73,18 @@ class BookmarkServiceTest extends ServiceTest {
|
|||
@Test
|
||||
void testClearDocumentBookmarks() throws BookmarkException {
|
||||
bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
bookmarkService.createBookmark("b");
|
||||
bookmarkService.clearBookmarks(document1);
|
||||
|
||||
documentService.selectDocument(document2);
|
||||
|
||||
bookmarkService.createBookmark("a");
|
||||
currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
bookmarkService.createBookmark("b");
|
||||
|
||||
assertEquals(2, bookmarkService.getBookmarks().getAllBookmarks().size());
|
||||
|
@ -87,6 +99,9 @@ class BookmarkServiceTest extends ServiceTest {
|
|||
@Test
|
||||
void testCreateBookmark() throws BookmarkException {
|
||||
Bookmark bookmarkA = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark bookmarkB = bookmarkService.createBookmark("b");
|
||||
|
||||
assertNotNull(bookmarkA);
|
||||
|
@ -100,6 +115,9 @@ class BookmarkServiceTest extends ServiceTest {
|
|||
documentService.selectDocument(document2);
|
||||
|
||||
bookmarkA = bookmarkService.createBookmark("a");
|
||||
currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
bookmarkB = bookmarkService.createBookmark("b");
|
||||
|
||||
assertNotNull(bookmarkA);
|
||||
|
@ -110,6 +128,9 @@ class BookmarkServiceTest extends ServiceTest {
|
|||
@Test
|
||||
void testDeleteBookmark() throws BookmarkException {
|
||||
Bookmark bookmarkA = bookmarkService.createBookmark("a");
|
||||
int currPage = documentService.getDocuments().getSelectedDocument().getCurrentPage().getPageNumber();
|
||||
int maxPages = documentService.getDocuments().getSelectedDocument().getPageCount();
|
||||
documentService.getDocuments().getSelectedDocument().selectPage((currPage + 1) % maxPages);
|
||||
Bookmark bookmarkB = bookmarkService.createBookmark("b");
|
||||
|
||||
bookmarkService.deleteBookmark(bookmarkB);
|
||||
|
|
|
@ -32,6 +32,7 @@ menu.quiz.embedded = Embedded quizzes
|
|||
menu.bookmarks = Bookmarks
|
||||
menu.bookmarks.clear = Delete all bookmarks
|
||||
menu.bookmarks.add = Bookmark current slide
|
||||
menu.bookmarks.remove = Remove current slide bookmark
|
||||
menu.bookmarks.previous = Go back to previous bookmark
|
||||
menu.bookmarks.goto = Go to bookmark
|
||||
menu.slide.actions = Slide Links
|
||||
|
|
|
@ -68,12 +68,12 @@ public class StylusListener implements org.lecturestudio.stylus.StylusListener {
|
|||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
Rectangle canvasBounds = slideView.getCanvasBounds();
|
||||
|
||||
viewBounds.setLocation(canvasBounds.getMinX(), canvasBounds.getMinY());
|
||||
viewBounds.setSize(canvasBounds.getWidth(), canvasBounds.getHeight());
|
||||
updateBounds(slideView.getCanvasBounds());
|
||||
}
|
||||
});
|
||||
slideView.addPropertyChangeListener("CanvasBounds", event -> {
|
||||
updateBounds((Rectangle) event.getNewValue());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -118,4 +118,9 @@ public class StylusListener implements org.lecturestudio.stylus.StylusListener {
|
|||
|
||||
handler.onButtonUp(stylusEvent, viewBounds);
|
||||
}
|
||||
|
||||
private void updateBounds(Rectangle canvasBounds) {
|
||||
viewBounds.setLocation(canvasBounds.getMinX(), canvasBounds.getMinY());
|
||||
viewBounds.setSize(canvasBounds.getWidth(), canvasBounds.getHeight());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,20 +20,22 @@ package org.lecturestudio.presenter.swing.view;
|
|||
|
||||
import static java.util.Objects.isNull;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
|
||||
import org.lecturestudio.core.app.dictionary.Dictionary;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.Interval;
|
||||
import org.lecturestudio.core.view.Action;
|
||||
import org.lecturestudio.core.view.ConsumerAction;
|
||||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
|
@ -47,10 +49,20 @@ import org.lecturestudio.swing.view.ViewPostConstruct;
|
|||
@SwingView(name = "goto-bookmark")
|
||||
public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkView {
|
||||
|
||||
private final Dictionary dictionary;
|
||||
|
||||
private Interval<Integer> slideBounds;
|
||||
|
||||
private ConsumerAction<Integer> gotoPageNumberAction;
|
||||
|
||||
private ConsumerAction<Bookmark> gotoBookmarkAction;
|
||||
|
||||
private ConsumerAction<Bookmark> deleteBookmarkAction;
|
||||
|
||||
private JLabel pageNumberLabel;
|
||||
|
||||
private JTextField slideNumberTextField;
|
||||
|
||||
private JTextField acceleratorTextField;
|
||||
|
||||
private JTable bookmarkTableView;
|
||||
|
@ -70,8 +82,22 @@ public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkVi
|
|||
};
|
||||
|
||||
|
||||
SwingGotoBookmarkView() {
|
||||
@Inject
|
||||
SwingGotoBookmarkView(Dictionary dictionary) {
|
||||
super();
|
||||
|
||||
this.dictionary = dictionary;
|
||||
this.slideBounds = new Interval<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocument(Document document) {
|
||||
String message = MessageFormat.format(dictionary.get("goto.slide.bounds"),
|
||||
1, document.getPageCount());
|
||||
|
||||
pageNumberLabel.setText(message);
|
||||
|
||||
slideBounds.set(1, document.getPageCount());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -95,6 +121,11 @@ public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkVi
|
|||
SwingUtils.bindAction(closeButton, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnGotoPageNumber(ConsumerAction<Integer> action) {
|
||||
gotoPageNumberAction = action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnGotoBookmark(ConsumerAction<Bookmark> action) {
|
||||
gotoBookmarkAction = action;
|
||||
|
@ -105,6 +136,23 @@ public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkVi
|
|||
deleteBookmarkAction = action;
|
||||
}
|
||||
|
||||
private void selectPageNumber() {
|
||||
String input = slideNumberTextField.getText();
|
||||
|
||||
if (input.isEmpty() || input.isBlank()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pageNumber = Integer.parseInt(input);
|
||||
|
||||
if (slideBounds.contains(pageNumber)) {
|
||||
executeAction(gotoPageNumberAction, pageNumber - 1);
|
||||
}
|
||||
else {
|
||||
pageNumberLabel.setForeground(Color.RED);
|
||||
}
|
||||
}
|
||||
|
||||
private void selectBookmark(int row) {
|
||||
if (row < 0) {
|
||||
return;
|
||||
|
@ -116,6 +164,18 @@ public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkVi
|
|||
executeAction(gotoBookmarkAction, selectedItem);
|
||||
}
|
||||
|
||||
private void findBookmark(String shortcut) {
|
||||
BookmarkTableModel model = (BookmarkTableModel) bookmarkTableView.getModel();
|
||||
|
||||
for (int i = 0; i < model.getRowCount(); i++) {
|
||||
Bookmark bookmark = model.getItem(i);
|
||||
|
||||
if (bookmark.getShortcut().equalsIgnoreCase(shortcut)) {
|
||||
executeAction(gotoBookmarkAction, bookmark);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewPostConstruct
|
||||
private void initialize() {
|
||||
bookmarkTableView.setModel(new BookmarkTableModel(
|
||||
|
@ -157,8 +217,7 @@ public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkVi
|
|||
char c = s.charAt(0);
|
||||
|
||||
if (Character.isLetter(c) || Character.isDigit(c)) {
|
||||
Bookmark bookmark = new Bookmark(String.valueOf(c));
|
||||
executeAction(gotoBookmarkAction, bookmark);
|
||||
findBookmark(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,8 +232,12 @@ public class SwingGotoBookmarkView extends ContentPane implements GotoBookmarkVi
|
|||
|
||||
}
|
||||
});
|
||||
acceleratorTextField.addHierarchyListener(e -> {
|
||||
acceleratorTextField.requestFocusInWindow();
|
||||
|
||||
slideNumberTextField.addActionListener(e -> {
|
||||
selectPageNumber();
|
||||
});
|
||||
slideNumberTextField.addHierarchyListener(e -> {
|
||||
slideNumberTextField.requestFocusInWindow();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,17 +35,12 @@ import org.lecturestudio.core.app.dictionary.Dictionary;
|
|||
import org.lecturestudio.core.beans.BooleanProperty;
|
||||
import org.lecturestudio.core.beans.IntegerProperty;
|
||||
import org.lecturestudio.core.beans.ObjectProperty;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.model.RecentDocument;
|
||||
import org.lecturestudio.core.model.Time;
|
||||
import org.lecturestudio.core.model.*;
|
||||
import org.lecturestudio.core.view.Action;
|
||||
import org.lecturestudio.core.view.ConsumerAction;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
import org.lecturestudio.presenter.api.context.PresenterContext.ParticipantCount;
|
||||
import org.lecturestudio.presenter.api.model.Bookmark;
|
||||
import org.lecturestudio.presenter.api.model.Bookmarks;
|
||||
import org.lecturestudio.presenter.api.model.MessageBarPosition;
|
||||
import org.lecturestudio.presenter.api.model.*;
|
||||
import org.lecturestudio.presenter.api.service.QuizWebServiceState;
|
||||
import org.lecturestudio.presenter.api.view.MenuView;
|
||||
import org.lecturestudio.swing.util.SwingUtils;
|
||||
|
@ -83,50 +78,68 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
|
||||
private JCheckBoxMenuItem fullscreenMenuItem;
|
||||
|
||||
private JCheckBoxMenuItem advancedSettingsMenuItem;
|
||||
|
||||
private JMenuItem customizeToolbarMenuItem;
|
||||
|
||||
private JMenu externalWindowsMenu;
|
||||
|
||||
private JCheckBoxMenuItem externalMessagesMenuItem;
|
||||
|
||||
private JCheckBoxMenuItem externalParticipantsMenuItem;
|
||||
|
||||
private JCheckBoxMenuItem externalSlidePreviewMenuItem;
|
||||
|
||||
private JCheckBoxMenuItem externalSpeechMenuItem;
|
||||
|
||||
private JCheckBoxMenuItem notesMenuItem;
|
||||
|
||||
private JMenu notesPositionMenu;
|
||||
|
||||
private JCheckBoxMenuItem externalNotesMenuItem;
|
||||
private JCheckBoxMenuItem slideNotesMenuItem;
|
||||
|
||||
private JMenu noteSlidePositionMenu;
|
||||
|
||||
private JMenu messagesPositionMenu;
|
||||
|
||||
private JMenu splitNotesPositionMenu;
|
||||
|
||||
private JMenu speechPositionMenu;
|
||||
|
||||
private JRadioButtonMenuItem speechPositionAbovePreviewMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem speechPositionExternalMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem splitNotesPositionRightMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem splitNotesPositionLeftMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem splitNotesPositionNoneMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem messagesPositionLeftMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem messagesPositionBottomMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem messagesPositionRightMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem messagesPositionExternalMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem notesPositionLeftMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem notesPositionBottomMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem notesPositionExternalMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem noteSlidePositionBelowPreviewMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem noteSlidePositionNoneMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem noteSlidePositionExternalMenuItem;
|
||||
|
||||
private JMenu participantsPositionMenu;
|
||||
|
||||
private JRadioButtonMenuItem participantsPositionLeftMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem participantsPositionRightMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem participantsPositionExternalMenuItem;
|
||||
|
||||
private JMenu previewPositionMenu;
|
||||
|
||||
private JRadioButtonMenuItem previewPositionLeftMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem previewPositionRightMenuItem;
|
||||
|
||||
private JRadioButtonMenuItem previewPositionExternalMenuItem;
|
||||
|
||||
private JMenuItem newWhiteboardMenuItem;
|
||||
|
||||
private JMenuItem newWhiteboardPageMenuItem;
|
||||
|
@ -153,6 +166,8 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
|
||||
private JCheckBoxMenuItem showNotesWindowMenuItem;
|
||||
|
||||
private JCheckBoxMenuItem showSlideNotesWindowMenuItem;
|
||||
|
||||
private JMenuItem selectQuizMenuItem;
|
||||
|
||||
private JMenuItem newQuizMenuItem;
|
||||
|
@ -169,10 +184,18 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
|
||||
private JMenuItem newBookmarkMenuItem;
|
||||
|
||||
private JMenuItem newDefaultBookmarkMenuItem;
|
||||
|
||||
private JMenuItem removeBookmarkMenuItem;
|
||||
|
||||
private JMenuItem gotoBookmarkMenuItem;
|
||||
|
||||
private JMenuItem previousBookmarkMenuItem;
|
||||
|
||||
private JMenuItem prevBookmarkMenuItem;
|
||||
|
||||
private JMenuItem nextBookmarkMenuItem;
|
||||
|
||||
private JMenuItem logMenuItem;
|
||||
|
||||
private JMenuItem aboutMenuItem;
|
||||
|
@ -219,14 +242,20 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
newBookmarkMenuItem.setEnabled(hasDocument);
|
||||
gotoBookmarkMenuItem.setEnabled(hasDocument);
|
||||
previousBookmarkMenuItem.setEnabled(hasDocument);
|
||||
prevBookmarkMenuItem.setEnabled(hasDocument);
|
||||
nextBookmarkMenuItem.setEnabled(hasDocument);
|
||||
newDefaultBookmarkMenuItem.setEnabled(hasDocument);
|
||||
removeBookmarkMenuItem.setEnabled(hasDocument);
|
||||
startRecordingMenuItem.setEnabled(hasDocument);
|
||||
enableStreamMenuItem.setEnabled(hasDocument);
|
||||
enableMessengerMenuItem.setEnabled(hasDocument);
|
||||
externalWindowsMenu.setEnabled(hasDocument);
|
||||
messagesPositionMenu.setEnabled(hasDocument);
|
||||
notesPositionMenu.setEnabled(hasDocument);
|
||||
participantsPositionMenu.setEnabled(hasDocument);
|
||||
previewPositionMenu.setEnabled(hasDocument);
|
||||
noteSlidePositionMenu.setEnabled(hasDocument);
|
||||
speechPositionMenu.setEnabled(hasDocument);
|
||||
splitNotesPositionMenu.setEnabled(hasDocument);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -333,172 +362,110 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
SwingUtils.bindBidirectional(outlineMenuItem, showProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdvancedSettings(boolean selected) {
|
||||
advancedSettingsMenuItem.setSelected(selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindFullscreen(BooleanProperty fullscreen) {
|
||||
SwingUtils.bindBidirectional(fullscreenMenuItem, fullscreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnAdvancedSettings(ConsumerAction<Boolean> action) {
|
||||
SwingUtils.bindAction(advancedSettingsMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnCustomizeToolbar(Action action) {
|
||||
SwingUtils.bindAction(customizeToolbarMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExternalMessages(boolean selected, boolean show) {
|
||||
externalMessagesMenuItem.setSelected(selected);
|
||||
externalMessagesMenuItem.setText(!selected || show
|
||||
? dict.get("menu.external.messages")
|
||||
: dict.get("menu.external.messages.disconnected"));
|
||||
public void setSpeechPosition(SpeechPosition position) {
|
||||
switch (position) {
|
||||
case ABOVE_SLIDE_PREVIEW -> speechPositionAbovePreviewMenuItem.setSelected(true);
|
||||
case EXTERNAL -> speechPositionExternalMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExternalNotes(boolean selected, boolean show) {
|
||||
externalNotesMenuItem.setSelected(selected);
|
||||
externalNotesMenuItem.setText(!selected || show
|
||||
? dict.get("menu.external.notes")
|
||||
: dict.get("menu.external.notes.disconnected"));
|
||||
public void setOnSpeechPosition(ConsumerAction<SpeechPosition> action) {
|
||||
SwingUtils.bindAction(speechPositionAbovePreviewMenuItem, () -> action.execute(SpeechPosition.ABOVE_SLIDE_PREVIEW));
|
||||
SwingUtils.bindAction(speechPositionExternalMenuItem, () -> action.execute(SpeechPosition.EXTERNAL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnExternalMessages(ConsumerAction<Boolean> action) {
|
||||
SwingUtils.bindAction(externalMessagesMenuItem, action);
|
||||
public void setMessagesPosition(MessageBarPosition position) {
|
||||
switch (position) {
|
||||
case LEFT -> messagesPositionLeftMenuItem.setSelected(true);
|
||||
case BOTTOM -> messagesPositionBottomMenuItem.setSelected(true);
|
||||
case RIGHT -> messagesPositionRightMenuItem.setSelected(true);
|
||||
case EXTERNAL -> messagesPositionExternalMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExternalParticipants(boolean selected, boolean show) {
|
||||
externalParticipantsMenuItem.setSelected(selected);
|
||||
externalParticipantsMenuItem.setText(!selected || show
|
||||
? dict.get("menu.external.participants")
|
||||
: dict.get("menu.external.participants.disconnected"));
|
||||
public void setOnMessagesPosition(ConsumerAction<MessageBarPosition> action) {
|
||||
SwingUtils.bindAction(messagesPositionLeftMenuItem, () -> action.execute(MessageBarPosition.LEFT));
|
||||
SwingUtils.bindAction(messagesPositionBottomMenuItem, () -> action.execute(MessageBarPosition.BOTTOM));
|
||||
SwingUtils.bindAction(messagesPositionRightMenuItem, () -> action.execute(MessageBarPosition.RIGHT));
|
||||
SwingUtils.bindAction(messagesPositionExternalMenuItem, () -> action.execute(MessageBarPosition.EXTERNAL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnExternalParticipants(ConsumerAction<Boolean> action) {
|
||||
SwingUtils.bindAction(externalParticipantsMenuItem, action);
|
||||
public void setSlideNotesPosition(SlideNotesPosition position) {
|
||||
switch (position) {
|
||||
case LEFT -> notesPositionLeftMenuItem.setSelected(true);
|
||||
case BOTTOM -> notesPositionBottomMenuItem.setSelected(true);
|
||||
case EXTERNAL -> notesPositionExternalMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExternalSlidePreview(boolean selected, boolean show) {
|
||||
externalSlidePreviewMenuItem.setSelected(selected);
|
||||
externalSlidePreviewMenuItem.setText(!selected || show
|
||||
? dict.get("menu.external.slide.preview")
|
||||
: dict.get("menu.external.slide.preview.disconnected"));
|
||||
public void setOnSlideNotesPosition(ConsumerAction<SlideNotesPosition> action) {
|
||||
SwingUtils.bindAction(notesPositionLeftMenuItem, () -> action.execute(SlideNotesPosition.LEFT));
|
||||
SwingUtils.bindAction(notesPositionBottomMenuItem, () -> action.execute(SlideNotesPosition.BOTTOM));
|
||||
SwingUtils.bindAction(notesPositionExternalMenuItem, () -> action.execute(SlideNotesPosition.EXTERNAL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnExternalSlidePreview(ConsumerAction<Boolean> action) {
|
||||
SwingUtils.bindAction(externalSlidePreviewMenuItem, action);
|
||||
public void setNoteSlidePosition(NoteSlidePosition position) {
|
||||
switch (position) {
|
||||
case NONE -> noteSlidePositionNoneMenuItem.setSelected(true);
|
||||
case BELOW_SLIDE_PREVIEW -> noteSlidePositionBelowPreviewMenuItem.setSelected(true);
|
||||
case EXTERNAL -> noteSlidePositionExternalMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExternalSpeech(boolean selected, boolean show) {
|
||||
externalSpeechMenuItem.setSelected(selected);
|
||||
externalSpeechMenuItem.setText(!selected || show
|
||||
? dict.get("menu.external.speech")
|
||||
: dict.get("menu.external.speech.disconnected"));
|
||||
public void setOnNoteSlidePosition(ConsumerAction<NoteSlidePosition> action) {
|
||||
SwingUtils.bindAction(noteSlidePositionNoneMenuItem, () -> action.execute(NoteSlidePosition.NONE));
|
||||
SwingUtils.bindAction(noteSlidePositionBelowPreviewMenuItem, () -> action.execute(NoteSlidePosition.BELOW_SLIDE_PREVIEW));
|
||||
SwingUtils.bindAction(noteSlidePositionExternalMenuItem, () -> action.execute(NoteSlidePosition.EXTERNAL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnExternalSpeech(ConsumerAction<Boolean> action) {
|
||||
SwingUtils.bindAction(externalSpeechMenuItem, action);
|
||||
public void setParticipantsPosition(ParticipantsPosition position) {
|
||||
switch (position) {
|
||||
case LEFT -> participantsPositionLeftMenuItem.setSelected(true);
|
||||
case RIGHT -> participantsPositionRightMenuItem.setSelected(true);
|
||||
case EXTERNAL -> participantsPositionExternalMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnExternalNotes(ConsumerAction<Boolean> action) {
|
||||
SwingUtils.bindAction(externalNotesMenuItem, action);
|
||||
public void setOnParticipantsPosition(ConsumerAction<ParticipantsPosition> action) {
|
||||
SwingUtils.bindAction(participantsPositionLeftMenuItem, () -> action.execute(ParticipantsPosition.LEFT));
|
||||
SwingUtils.bindAction(participantsPositionRightMenuItem, () -> action.execute(ParticipantsPosition.RIGHT));
|
||||
SwingUtils.bindAction(participantsPositionExternalMenuItem, () -> action.execute(ParticipantsPosition.EXTERNAL));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMessagesPositionLeft(Action action) {
|
||||
SwingUtils.bindAction(messagesPositionLeftMenuItem, action);
|
||||
public void setSlidePreviewPosition(SlidePreviewPosition position) {
|
||||
switch (position) {
|
||||
case LEFT -> previewPositionLeftMenuItem.setSelected(true);
|
||||
case RIGHT -> previewPositionRightMenuItem.setSelected(true);
|
||||
case EXTERNAL -> previewPositionExternalMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessagesPositionLeft() {
|
||||
messagesPositionLeftMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMessagesPositionBottom(Action action) {
|
||||
SwingUtils.bindAction(messagesPositionBottomMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessagesPositionBottom() {
|
||||
messagesPositionBottomMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMessagesPositionRight(Action action) {
|
||||
SwingUtils.bindAction(messagesPositionRightMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessagesPositionRight() {
|
||||
messagesPositionRightMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnNotesPositionBottom(Action action) {
|
||||
SwingUtils.bindAction(notesPositionBottomMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotesPositionBottom() {
|
||||
notesPositionBottomMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setOnNotesPositionLeft(Action action) {
|
||||
SwingUtils.bindAction(notesPositionLeftMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNotesPositionLeft() {
|
||||
notesPositionLeftMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnParticipantsPositionLeft(Action action) {
|
||||
SwingUtils.bindAction(participantsPositionLeftMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParticipantsPositionLeft() {
|
||||
participantsPositionLeftMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnParticipantsPositionRight(Action action) {
|
||||
SwingUtils.bindAction(participantsPositionRightMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParticipantsPositionRight() {
|
||||
participantsPositionRightMenuItem.setSelected(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindPreviewPosition(ObjectProperty<MessageBarPosition> position) {
|
||||
setPreviewPosition(position.get());
|
||||
|
||||
position.addListener((o, oldPos, newPos) -> {
|
||||
setPreviewPosition(newPos);
|
||||
});
|
||||
|
||||
previewPositionLeftMenuItem.addActionListener(e -> position.set(MessageBarPosition.LEFT));
|
||||
previewPositionRightMenuItem.addActionListener(e -> position.set(MessageBarPosition.RIGHT));
|
||||
public void setOnSlidePreviewPosition(ConsumerAction<SlidePreviewPosition> action) {
|
||||
SwingUtils.bindAction(previewPositionLeftMenuItem, () -> action.execute(SlidePreviewPosition.LEFT));
|
||||
SwingUtils.bindAction(previewPositionRightMenuItem, () -> action.execute(SlidePreviewPosition.RIGHT));
|
||||
SwingUtils.bindAction(previewPositionExternalMenuItem, () -> action.execute(SlidePreviewPosition.EXTERNAL));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -671,7 +638,7 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
public void setBookmarks(Bookmarks bookmarks) {
|
||||
SwingUtils.invoke(() -> {
|
||||
List<Bookmark> bookmarkList = bookmarks.getAllBookmarks();
|
||||
int fixedMenuItems = 5;
|
||||
int fixedMenuItems = 10;
|
||||
|
||||
// Remove all bookmark menu items.
|
||||
if (bookmarksMenu.getItemCount() > fixedMenuItems) {
|
||||
|
@ -716,6 +683,16 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
SwingUtils.bindAction(newBookmarkMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnCreateNewDefaultBookmarkView(Action action) {
|
||||
SwingUtils.bindAction(newDefaultBookmarkMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnRemoveBookmarkView(Action action) {
|
||||
SwingUtils.bindAction(removeBookmarkMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnShowGotoBookmarkView(Action action) {
|
||||
SwingUtils.bindAction(gotoBookmarkMenuItem, action);
|
||||
|
@ -726,6 +703,16 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
SwingUtils.bindAction(previousBookmarkMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnPrevBookmark(Action action) {
|
||||
SwingUtils.bindAction(prevBookmarkMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnNextBookmark(Action action) {
|
||||
SwingUtils.bindAction(nextBookmarkMenuItem, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnOpenBookmark(ConsumerAction<Bookmark> action) {
|
||||
this.openBookmarkAction = action;
|
||||
|
@ -803,6 +790,22 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSplitNotesPosition(NotesPosition position) {
|
||||
switch (position) {
|
||||
case LEFT -> splitNotesPositionLeftMenuItem.setSelected(true);
|
||||
case RIGHT -> splitNotesPositionRightMenuItem.setSelected(true);
|
||||
case NONE -> splitNotesPositionNoneMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnSplitNotesPosition(ConsumerAction<NotesPosition> action) {
|
||||
SwingUtils.bindAction(splitNotesPositionNoneMenuItem, () -> action.execute(NotesPosition.NONE));
|
||||
SwingUtils.bindAction(splitNotesPositionLeftMenuItem, () -> action.execute(NotesPosition.LEFT));
|
||||
SwingUtils.bindAction(splitNotesPositionRightMenuItem, () -> action.execute(NotesPosition.RIGHT));
|
||||
}
|
||||
|
||||
@ViewPostConstruct
|
||||
private void initialize() {
|
||||
setStateText(enableStreamMenuItem, dict.get("menu.stream.start"),
|
||||
|
@ -814,16 +817,6 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
setStateText(enableStreamCameraMenuItem, dict.get("menu.stream.camera.start"),
|
||||
dict.get("menu.stream.camera.stop"));
|
||||
|
||||
// TODO: Creation of ButtonGroup can be removed here and can be set in the view xml.
|
||||
final ButtonGroup messagesPositionButtonGroup = new ButtonGroup();
|
||||
messagesPositionButtonGroup.add(messagesPositionLeftMenuItem);
|
||||
messagesPositionButtonGroup.add(messagesPositionBottomMenuItem);
|
||||
messagesPositionButtonGroup.add(messagesPositionRightMenuItem);
|
||||
|
||||
final ButtonGroup participantsPositionButtonGroup = new ButtonGroup();
|
||||
participantsPositionButtonGroup.add(participantsPositionLeftMenuItem);
|
||||
participantsPositionButtonGroup.add(participantsPositionRightMenuItem);
|
||||
|
||||
stopwatchMenu.setBorderPainted(false);
|
||||
stopwatchMenu.setFocusPainted(false);
|
||||
stopwatchMenu.addMouseListener(new MouseAdapter() {
|
||||
|
@ -867,11 +860,4 @@ public class SwingMenuView extends JMenuBar implements MenuView {
|
|||
recordIndicatorMenu.setText(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void setPreviewPosition(MessageBarPosition position) {
|
||||
switch (position) {
|
||||
case LEFT -> previewPositionLeftMenuItem.setSelected(true);
|
||||
case RIGHT -> previewPositionRightMenuItem.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -45,6 +45,7 @@ import javax.swing.JSeparator;
|
|||
import javax.swing.JToggleButton;
|
||||
|
||||
import org.lecturestudio.core.ExecutableState;
|
||||
import org.lecturestudio.core.app.dictionary.Dictionary;
|
||||
import org.lecturestudio.core.beans.BooleanProperty;
|
||||
import org.lecturestudio.core.controller.ToolController;
|
||||
import org.lecturestudio.core.graphics.Color;
|
||||
|
@ -59,6 +60,7 @@ import org.lecturestudio.core.view.Action;
|
|||
import org.lecturestudio.core.view.ConsumerAction;
|
||||
import org.lecturestudio.core.view.PresentationParameter;
|
||||
import org.lecturestudio.presenter.api.view.ToolbarView;
|
||||
import org.lecturestudio.swing.AwtResourceLoader;
|
||||
import org.lecturestudio.swing.components.FontPickerButton;
|
||||
import org.lecturestudio.swing.components.RecordButton;
|
||||
import org.lecturestudio.swing.components.ToolColorPickerButton;
|
||||
|
@ -96,6 +98,12 @@ public class SwingToolbarView extends JPanel implements ToolbarView {
|
|||
|
||||
private JButton nextSlideButton;
|
||||
|
||||
private JButton prevBookmarkButton;
|
||||
|
||||
private JButton nextBookmarkButton;
|
||||
|
||||
private JButton newBookmarkButton;
|
||||
|
||||
private ToolColorPickerButton customColorButton;
|
||||
|
||||
private JToggleButton colorButton1;
|
||||
|
@ -168,11 +176,19 @@ public class SwingToolbarView extends JPanel implements ToolbarView {
|
|||
|
||||
private CustomizedToolbar customizedToolbar;
|
||||
|
||||
private final Dictionary dict;
|
||||
|
||||
private static final String REMOVE_BOOKMARK_KEY = "menu.bookmarks.remove";
|
||||
|
||||
private static final String ADD_BOOKMARK_KEY = "menu.bookmarks.add";
|
||||
|
||||
|
||||
|
||||
@Inject
|
||||
SwingToolbarView(ResourceBundle resourceBundle, ToolController toolController) {
|
||||
SwingToolbarView(Dictionary dict, ResourceBundle resourceBundle, ToolController toolController) {
|
||||
super();
|
||||
|
||||
this.dict = dict;
|
||||
this.resourceBundle = resourceBundle;
|
||||
this.toolController = toolController;
|
||||
|
||||
|
@ -271,6 +287,23 @@ public class SwingToolbarView extends JPanel implements ToolbarView {
|
|||
SwingUtils.bindAction(nextSlideButton, action);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setOnPreviousBookmark(Action action) {
|
||||
SwingUtils.bindAction(prevBookmarkButton, action);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setOnNextBookmark(Action action) {
|
||||
SwingUtils.bindAction(nextBookmarkButton, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnNewBookmark(Action action) {
|
||||
SwingUtils.bindAction(newBookmarkButton, action);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnCustomPaletteColor(ConsumerAction<Color> action) {
|
||||
this.paletteColorAction = action;
|
||||
|
@ -521,6 +554,17 @@ public class SwingToolbarView extends JPanel implements ToolbarView {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectNewBookmarkButton(boolean hasBookmark){
|
||||
if (hasBookmark){
|
||||
newBookmarkButton.setIcon(AwtResourceLoader.getIcon("bookmark-remove.svg", 24));
|
||||
newBookmarkButton.setToolTipText(dict.get(REMOVE_BOOKMARK_KEY));
|
||||
} else {
|
||||
newBookmarkButton.setIcon(AwtResourceLoader.getIcon("bookmark-add.svg", 24));
|
||||
newBookmarkButton.setToolTipText(dict.get(ADD_BOOKMARK_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectToolButton(ToolType toolType) {
|
||||
SwingUtils.invoke(() -> {
|
||||
|
|
|
@ -35,10 +35,10 @@ public class BookmarkTableModel extends TableModelBase<Bookmark> {
|
|||
|
||||
switch (columnIndex) {
|
||||
case 0:
|
||||
return bookmark.getPage().getDocument().getTitle();
|
||||
return bookmark.getPage().getDocument().getName();
|
||||
|
||||
case 1:
|
||||
return bookmark.getPage().getPageNumber();
|
||||
return bookmark.getPage().getPageNumber() + 1;
|
||||
|
||||
case 2:
|
||||
return bookmark.getShortcut();
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="m 50,32.500285 a 2.1875353,2.1875353 0 0 1 2.187535,2.187535 v 6.562606 h 6.562606 a 2.1875353,2.1875353 0 0 1 0,4.37507 h -6.562606 v 6.562606 a 2.1875355,2.1875355 0 0 1 -4.375071,0 v -6.562606 h -6.562605 a 2.1875353,2.1875353 0 0 1 0,-4.37507 h 6.562605 V 34.68782 A 2.1875353,2.1875353 0 0 1 50,32.500285 Z M 23.749576,23.750143 a 8.7501413,8.7501413 0 0 1 8.750141,-8.750141 h 35.000565 a 8.7501413,8.7501413 0 0 1 8.750142,8.750141 v 59.06345 a 2.1875353,2.1875353 0 0 1 -3.39943,1.82003 L 50,72.317802 27.149006,84.633623 a 2.1875353,2.1875353 0 0 1 -3.39943,-1.82003 z m 8.750141,-4.37507 a 4.3750706,4.3750706 0 0 0 -4.37507,4.37507 v 54.97714 L 48.788105,67.868355 a 2.1875353,2.1875353 0 0 1 2.423789,0 l 20.663459,10.858928 v -54.97714 a 4.3750706,4.3750706 0 0 0 -4.375071,-4.37507 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M 42.908645,58.410205 V 33.589796 l 14.182732,12.410203 z m 1.705224,1.948471 14.180157,-12.410191 a 2.5876182,2.5876182 0 0 0 0,-3.89697 L 44.613869,31.641324 a 2.5876182,2.5876182 0 0 0 -4.292817,1.948472 v 24.820409 a 2.5876182,2.5876182 0 0 0 4.292817,1.948471 z M 23.749576,23.750141 A 8.7501413,8.7501413 0 0 1 32.499717,15 h 35.000565 a 8.7501413,8.7501413 0 0 1 8.750142,8.750141 v 59.063454 a 2.1875353,2.1875353 0 0 1 -3.39943,1.820029 L 50,72.3178 27.149006,84.633624 a 2.1875353,2.1875353 0 0 1 -3.39943,-1.820029 z m 8.750141,-4.37507 a 4.3750706,4.3750706 0 0 0 -4.37507,4.37507 V 78.727279 L 48.788105,67.868353 a 2.1875353,2.1875353 0 0 1 2.423789,0 L 71.875353,78.727279 V 23.750141 a 4.3750706,4.3750706 0 0 0 -4.375071,-4.37507 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 990 B |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M 57.091355,58.410205 V 33.589796 L 42.908623,45.999999 Z M 55.386131,60.358676 41.205974,47.948485 a 2.5876182,2.5876182 0 0 1 0,-3.89697 L 55.386131,31.641324 a 2.5876182,2.5876182 0 0 1 4.292817,1.948472 v 24.820409 a 2.5876182,2.5876182 0 0 1 -4.292817,1.948471 z M 23.749576,23.750141 A 8.7501413,8.7501413 0 0 1 32.499717,15 h 35.000565 a 8.7501413,8.7501413 0 0 1 8.750142,8.750141 v 59.063454 a 2.1875353,2.1875353 0 0 1 -3.39943,1.820029 L 50,72.3178 27.149006,84.633624 a 2.1875353,2.1875353 0 0 1 -3.39943,-1.820029 z m 8.750141,-4.37507 a 4.3750706,4.3750706 0 0 0 -4.37507,4.37507 V 78.727279 L 48.788105,67.868353 a 2.1875353,2.1875353 0 0 1 2.423789,0 L 71.875353,78.727279 V 23.750141 a 4.3750706,4.3750706 0 0 0 -4.375071,-4.37507 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 991 B |
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 100 100"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M 23.749575,23.750142 A 8.7501418,8.7501418 0 0 1 32.499715,15 H 67.50028 a 8.7501418,8.7501418 0 0 1 8.750146,8.750142 v 59.063457 a 2.1875354,2.1875354 0 0 1 -3.399431,1.820025 L 50,72.317804 27.149004,84.633624 a 2.1875354,2.1875354 0 0 1 -3.399429,-1.820025 z m 8.750142,-4.375071 a 4.3750709,4.3750709 0 0 0 -4.375072,4.375071 v 54.977141 l 20.66346,-10.858926 a 2.1875354,2.1875354 0 0 1 2.423789,0 L 71.875348,78.727283 V 23.750142 A 4.3750709,4.3750709 0 0 0 67.50028,19.375071 Z m 6.562605,24.062889 a 2.1875354,2.1875354 0 0 1 2.187537,-2.187535 H 58.75014 a 2.1875355,2.1875355 0 0 1 0,4.375071 H 41.249859 A 2.1875354,2.1875354 0 0 1 39.062322,43.43796 Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 908 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<path d="M 17.691 40.129 A 2.692 2.692 0 0 0 15 42.82 A 2.692 2.692 0 0 0 17.691 45.514 H 67.95 A 2.692 2.692 0 0 0 70.642 42.82 A 2.692 2.692 0 0 0 67.95 40.129 H 17.691 Z M 17.691 25.77 A 2.692 2.692 0 0 0 15 28.46 A 2.692 2.692 0 0 0 17.691 31.154 H 82.31 A 2.692 2.692 0 0 0 85 28.461 A 2.692 2.692 0 0 0 82.309 25.77 H 17.69 Z M 17.691 54.486 A 2.692 2.692 0 0 0 15 57.18 A 2.692 2.692 0 0 0 17.691 59.871 H 82.31 A 2.692 2.692 0 0 0 85 57.18 A 2.692 2.692 0 0 0 82.309 54.486 H 17.69 Z M 17.691 68.846 A 2.692 2.692 0 0 0 15 71.539 A 2.692 2.692 0 0 0 17.691 74.23 H 67.95 A 2.692 2.692 0 0 0 70.642 71.54 A 2.692 2.692 0 0 0 67.95 68.846 H 17.691 Z" />
|
||||
</svg>
|
After Width: | Height: | Size: 732 B |
|
@ -1,14 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Panel name="goto.bookmark.title">
|
||||
<Panel layout="GridBagLayout" border="EmptyBorder(0, 20, 20, 20)">
|
||||
<Label text="goto.bookmark.key" border="EmptyBorder(0, 0, 5, 0)">
|
||||
<Label text="goto.slide.title" border="EmptyBorder(0, 0, 5, 0)">
|
||||
<gridbagconstraints gridx="0" gridy="0" fill="GridBagConstraints.BOTH" />
|
||||
</Label>
|
||||
<TextField id="acceleratorTextField" text="">
|
||||
<TextField id="slideNumberTextField" text="">
|
||||
<gridbagconstraints gridx="0" gridy="1" fill="GridBagConstraints.BOTH" />
|
||||
<Filter class="org.lecturestudio.swing.filter.IntFilter" />
|
||||
</TextField>
|
||||
<Label id="pageNumberLabel" border="EmptyBorder(3, 0, 5, 0)">
|
||||
<gridbagconstraints gridx="0" gridy="2" fill="GridBagConstraints.BOTH" />
|
||||
</Label>
|
||||
<Label text="goto.bookmark.key" border="EmptyBorder(15, 0, 5, 0)">
|
||||
<gridbagconstraints gridx="0" gridy="3" fill="GridBagConstraints.BOTH" />
|
||||
</Label>
|
||||
<TextField id="acceleratorTextField" text="">
|
||||
<gridbagconstraints gridx="0" gridy="4" fill="GridBagConstraints.BOTH" />
|
||||
</TextField>
|
||||
<ScrollPane border="EmptyBorder(10, 0, 0, 0)">
|
||||
<gridbagconstraints gridx="0" gridy="2" weightx="1.0" weighty="1.0" fill="GridBagConstraints.BOTH" />
|
||||
<gridbagconstraints gridx="0" gridy="5" weightx="1.0" weighty="1.0" fill="GridBagConstraints.BOTH" />
|
||||
<Table id="bookmarkTableView" autoCreateColumnsFromModel="false" fillsViewportHeight="true" rowHeight="25" selectionMode="ListSelectionModel.SINGLE_SELECTION">
|
||||
<TableColumn headerValue="goto.bookmark.document" />
|
||||
<TableColumn headerValue="goto.bookmark.slide.number" maxWidth="65" />
|
||||
|
@ -20,7 +30,7 @@
|
|||
</Table>
|
||||
</ScrollPane>
|
||||
<HBox gap="5" border="EmptyBorder(10, 0, 0, 0)">
|
||||
<gridbagconstraints gridx="0" gridy="3" fill="GridBagConstraints.HORIZONTAL" />
|
||||
<gridbagconstraints gridx="0" gridy="6" fill="GridBagConstraints.HORIZONTAL" />
|
||||
<box.hglue />
|
||||
<Button id="closeButton" text="button.close"/>
|
||||
</HBox>
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
goto.bookmark.title = Lesezeichen anspringen
|
||||
goto.bookmark.title = Folien und Lesezeichen anspringen
|
||||
goto.bookmark.document = Dokument
|
||||
goto.bookmark.key = Taste
|
||||
goto.bookmark.key = Lesezeichentaste
|
||||
goto.bookmark.slide.number = Folien #
|
||||
goto.bookmark.delete = Lesezeichen l\u00f6schen
|
||||
goto.bookmark.delete = Lesezeichen l\u00f6schen
|
||||
|
||||
goto.slide.title = Foliennummer
|
||||
goto.slide.bounds = Folie {0} bis {1}
|
|
@ -1,5 +1,8 @@
|
|||
goto.bookmark.title = Navigate to bookmarks
|
||||
goto.bookmark.title = Navigate to slides and bookmarks
|
||||
goto.bookmark.document = Document
|
||||
goto.bookmark.key = Key
|
||||
goto.bookmark.key = Bookmark key
|
||||
goto.bookmark.slide.number = Slide #
|
||||
goto.bookmark.delete = Delete bookmark
|
||||
goto.bookmark.delete = Delete bookmark
|
||||
|
||||
goto.slide.title = Slide number
|
||||
goto.slide.bounds = Slide {0} to {1}
|
|
@ -15,39 +15,58 @@
|
|||
<menuitem id="settingsMenuItem" text="menu.options" />
|
||||
</menu>
|
||||
<menu text="menu.view">
|
||||
<checkboxmenuitem id="outlineMenuItem" text="menu.contents" />
|
||||
<checkboxmenuitem id="fullscreenMenuItem" text="menu.fullscreen" type="checkbox" accelerator="alt ENTER" />
|
||||
<menuitem id="customizeToolbarMenuItem" text="menu.toolbar.customize" />
|
||||
<menu id="externalWindowsMenu" text="menu.external.windows">
|
||||
<checkboxmenuitem id="externalMessagesMenuItem" text="menu.external.messages" />
|
||||
<checkboxmenuitem id="externalParticipantsMenuItem" text="menu.external.participants" />
|
||||
<checkboxmenuitem id="externalSlidePreviewMenuItem" text="menu.external.slide.preview" />
|
||||
<checkboxmenuitem id="externalSpeechMenuItem" text="menu.external.speech" />
|
||||
<checkboxmenuitem id="externalNotesMenuItem" text="menu.external.notes" />
|
||||
</menu>
|
||||
<checkboxmenuitem id="outlineMenuItem" text="menu.contents" />
|
||||
<separator />
|
||||
<menu id="messagesPositionMenu" text="menu.messages.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="messagesPositionLeftMenuItem" text="menu.left" />
|
||||
<radiobuttonmenuitem id="messagesPositionBottomMenuItem" text="menu.bottom" />
|
||||
<radiobuttonmenuitem id="messagesPositionRightMenuItem" text="menu.right" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<menu id="notesPositionMenu" text="menu.notes.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="notesPositionLeftMenuItem" text="menu.left" />
|
||||
<radiobuttonmenuitem id="notesPositionBottomMenuItem" text="menu.bottom" />
|
||||
<radiobuttonmenuitem id="messagesPositionBottomMenuItem" text="menu.bottom" />
|
||||
<radiobuttonmenuitem id="messagesPositionExternalMenuItem" text="menu.external" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<menu id="participantsPositionMenu" text="menu.participants.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="participantsPositionLeftMenuItem" text="menu.left" />
|
||||
<radiobuttonmenuitem id="participantsPositionRightMenuItem" text="menu.right" />
|
||||
<radiobuttonmenuitem id="participantsPositionExternalMenuItem" text="menu.external" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<menu id="previewPositionMenu" text="menu.preview.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="previewPositionLeftMenuItem" text="menu.left" />
|
||||
<radiobuttonmenuitem id="previewPositionRightMenuItem" text="menu.right" />
|
||||
<radiobuttonmenuitem id="previewPositionExternalMenuItem" text="menu.external" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<menu id="notesPositionMenu" text="menu.notes.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="notesPositionLeftMenuItem" text="menu.left" />
|
||||
<radiobuttonmenuitem id="notesPositionBottomMenuItem" text="menu.bottom" />
|
||||
<radiobuttonmenuitem id="notesPositionExternalMenuItem" text="menu.external" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<menu id="noteSlidePositionMenu" text="menu.note.slide.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="noteSlidePositionBelowPreviewMenuItem" text="menu.note.slide.below.preview" />
|
||||
<radiobuttonmenuitem id="noteSlidePositionNoneMenuItem" text="menu.none" />
|
||||
<radiobuttonmenuitem id="noteSlidePositionExternalMenuItem" text="menu.external" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<menu id="speechPositionMenu" text="menu.speech.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="speechPositionAbovePreviewMenuItem" text="menu.speech.position.above.preview" />
|
||||
<radiobuttonmenuitem id="speechPositionExternalMenuItem" text="menu.external" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
<separator />
|
||||
<menu id="splitNotesPositionMenu" text="menu.splitNotes.position">
|
||||
<buttongroup>
|
||||
<radiobuttonmenuitem id="splitNotesPositionLeftMenuItem" text="menu.left" />
|
||||
<radiobuttonmenuitem id="splitNotesPositionRightMenuItem" text="menu.right" />
|
||||
<radiobuttonmenuitem id="splitNotesPositionNoneMenuItem" text="menu.none" />
|
||||
</buttongroup>
|
||||
</menu>
|
||||
</menu>
|
||||
|
@ -69,7 +88,6 @@
|
|||
<checkboxmenuitem id="enableStreamCameraMenuItem" text="menu.stream.camera.start" type="checkbox" selected="true" enabled="false" />
|
||||
<separator />
|
||||
<checkboxmenuitem id="enableMessengerMenuItem" text="menu.messenger.start" enabled="false" />
|
||||
<!-- <checkboxmenuitem id="showMessengerWindowMenuItem" text="menu.messenger.window.visible" type="checkbox" selected="true" enabled="false" />-->
|
||||
<separator />
|
||||
<menuitem id="selectQuizMenuItem" text="menu.quiz.selection" accelerator="Z" enabled="false" />
|
||||
<menuitem id="newQuizMenuItem" text="menu.quiz.new" enabled="false" />
|
||||
|
@ -82,9 +100,14 @@
|
|||
<menu id="bookmarksMenu" text="menu.bookmarks">
|
||||
<menuitem id="clearBookmarksMenuItem" text="menu.bookmarks.clear" enabled="false" />
|
||||
<menuitem id="newBookmarkMenuItem" text="menu.bookmarks.add" accelerator="B" enabled="false" />
|
||||
<menuitem id="removeBookmarkMenuItem" text="menu.bookmarks.remove" enabled="false" />
|
||||
<menuitem id="newDefaultBookmarkMenuItem" text="menu.bookmarks.add.default" enabled="false" />
|
||||
<separator />
|
||||
<menuitem id="gotoBookmarkMenuItem" text="menu.bookmarks.goto" accelerator="G" enabled="false" />
|
||||
<menuitem id="previousBookmarkMenuItem" text="menu.bookmarks.previous" accelerator="L" enabled="false" />
|
||||
<separator />
|
||||
<menuitem id="prevBookmarkMenuItem" text="menu.bookmarks.prev" enabled="false" />
|
||||
<menuitem id="nextBookmarkMenuItem" text="menu.bookmarks.next" enabled="false" />
|
||||
</menu>
|
||||
<menu text="menu.info">
|
||||
<menuitem id="logMenuItem" text="menu.log" />
|
||||
|
|
|
@ -13,9 +13,11 @@ menu.participants = Teilnehmer:innen
|
|||
menu.fullscreen = Vollbild
|
||||
menu.advanced.settings = Erweiterte Einstellungen
|
||||
menu.toolbar.customize = Toolbar anpassen
|
||||
menu.external.windows = Externe Fenster
|
||||
menu.external.window = Externes Fenster
|
||||
menu.external.notes = Notizen
|
||||
menu.external.notes.disconnected = Notizen (Bildschirm getrennt)
|
||||
menu.external.slide.notes = Notiz-Folien
|
||||
menu.external.slide.notes.disconnected = Notiz-Folien (Bildschirm getrennt)
|
||||
menu.external.messages = Nachrichten
|
||||
menu.external.messages.disconnected = Nachrichten (Bildschirm getrennt)
|
||||
menu.external.participants = Teilnehmer:innen
|
||||
|
@ -26,11 +28,17 @@ menu.external.speech = Redebeitrag
|
|||
menu.external.speech.disconnected = Redebeitrag (Bildschirm getrennt)
|
||||
menu.messages.position = Position der Nachrichten
|
||||
menu.notes.position = Position der Notizen
|
||||
menu.note.slide.position = Position der Notiz-Folien
|
||||
menu.note.slide.below.preview = Unter der Folienvorschau
|
||||
menu.participants.position = Position der Teilnehmer:innen
|
||||
menu.preview.position = Position der Folienvorschau
|
||||
menu.speech.position = Position des Redebeitrags
|
||||
menu.speech.position.above.preview = \u00DCber der Folienvorschau
|
||||
menu.left = Links
|
||||
menu.bottom = Unten
|
||||
menu.right = Rechts
|
||||
menu.external = Extern
|
||||
menu.none = Ohne
|
||||
menu.whiteboard = Whiteboard
|
||||
menu.whiteboard.new = Whiteboard erstellen
|
||||
menu.grid = Gitternetz ein/ausschalten
|
||||
|
@ -60,11 +68,16 @@ menu.quiz.embedded = Eingebettete Quizzes
|
|||
menu.bookmarks = Lesezeichen
|
||||
menu.bookmarks.clear = Alle Lesezeichen l\u00F6schen
|
||||
menu.bookmarks.add = Aktuelle Folie als Lesezeichen
|
||||
menu.bookmarks.remove = Lesezeichen auf aktueller Folie l\u00F6schen
|
||||
menu.bookmarks.add.default = Aktuelle Folie als Lesezeichen (Standard-K\u00FCrzel)
|
||||
menu.bookmarks.previous = Zur\u00FCck zur letzten Position
|
||||
menu.bookmarks.goto = Lesezeichen anspringen
|
||||
menu.slide.actions = Folienlinks
|
||||
menu.log = Log
|
||||
menu.about = \u00DCber
|
||||
menu.stopwatch.stop = Stoppuhr zurücksetzen
|
||||
menu.stopwatch.stop = Stoppuhr zur\u00FCcksetzen
|
||||
menu.stopwatch.pause = Stoppuhr Starten/Anhalten
|
||||
menu.stopwatch.config = Stoppuhr Einstellungen
|
||||
menu.stopwatch.config = Stoppuhr Einstellungen
|
||||
menu.bookmarks.prev = Zum vorherigen Lesezeichen springen
|
||||
menu.bookmarks.next = Zum n\u00E4chsten Lesezeichen springen
|
||||
menu.splitNotes.position = Notiz-Folie
|
||||
|
|
|
@ -13,8 +13,9 @@ menu.participants = Participants
|
|||
menu.fullscreen = Fullscreen
|
||||
menu.advanced.settings = Advanced settings
|
||||
menu.toolbar.customize = Customize toolbar
|
||||
menu.external.windows = External windows
|
||||
menu.external.window = External window
|
||||
menu.external.notes = Notes
|
||||
menu.external.slide.notes = Slide notes
|
||||
menu.external.notes.disconnected = Notes (Display disconnected)
|
||||
menu.external.messages = Messages
|
||||
menu.external.messages.disconnected = Messages (Display disconnected)
|
||||
|
@ -26,11 +27,17 @@ menu.external.speech = Speech
|
|||
menu.external.speech.disconnected = Speech (Display disconnected)
|
||||
menu.messages.position = Messages position
|
||||
menu.notes.position = Notes position
|
||||
menu.note.slide.position = Slide note position
|
||||
menu.note.slide.below.preview = Below the slide preview
|
||||
menu.participants.position = Participants position
|
||||
menu.preview.position = Slide preview position
|
||||
menu.speech.position = Speech position
|
||||
menu.speech.position.above.preview = Above the slide preview
|
||||
menu.left = Left
|
||||
menu.bottom = Bottom
|
||||
menu.right = Right
|
||||
menu.external = External
|
||||
menu.none = None
|
||||
menu.whiteboard = Whiteboard
|
||||
menu.whiteboard.new = Create whiteboard
|
||||
menu.grid = Switch grid on/off
|
||||
|
@ -60,6 +67,8 @@ menu.quiz.embedded = Embedded quizzes
|
|||
menu.bookmarks = Bookmarks
|
||||
menu.bookmarks.clear = Delete all bookmarks
|
||||
menu.bookmarks.add = Bookmark current slide
|
||||
menu.bookmarks.remove = Remove bookmark current slide
|
||||
menu.bookmarks.add.default = Bookmark current slide (default shortcut)
|
||||
menu.bookmarks.previous = Go back to previous bookmark
|
||||
menu.bookmarks.goto = Go to bookmark
|
||||
menu.slide.actions = Slide Links
|
||||
|
@ -68,3 +77,6 @@ menu.about = About
|
|||
menu.stopwatch.stop = reset stopwatch
|
||||
menu.stopwatch.pause = start/pause stopwatch
|
||||
menu.stopwatch.config = Stopwatch configuration
|
||||
menu.bookmarks.prev = Go to previous bookmark
|
||||
menu.bookmarks.next = Go to next bookmark
|
||||
menu.splitNotes.position = Notes slide
|
||||
|
|
|
@ -4,20 +4,24 @@
|
|||
<SplitPane id="tabSplitPane" dividerSize="10" resizeWeight="1" orientation="JSplitPane.HORIZONTAL_SPLIT" constraints="BorderLayout.CENTER">
|
||||
<SplitPane id="notesSplitPane" dividerSize="10" resizeWeight="1" orientation="JSplitPane.VERTICAL_SPLIT">
|
||||
<SplitPane id="docSplitPane" dividerSize="10" resizeWeight="0" focusable="false" orientation="JSplitPane.HORIZONTAL_SPLIT">
|
||||
<AdaptiveTabbedPane id="leftTabPane" tabPlacement="JTabbedPane.LEFT" >
|
||||
<Tab id="participantsTab" name="participants" text="slides.participants" icon="participants.svg, 18" defaultTabType="AdaptiveTabType.PARTICIPANTS">
|
||||
<Panel id="participantsPanel" layout="BorderLayout">
|
||||
<ParticipantList id="participantList" constraints="BorderLayout.CENTER" />
|
||||
</Panel>
|
||||
</Tab>
|
||||
<Tab id="outlineTab" name="outline" text="menu.contents">
|
||||
<ScrollPane id="outlinePane">
|
||||
<Tree id="outlineTree" name="tree" focusable="false" rootVisible="false" showsRootHandles="true">
|
||||
<renderer class="org.lecturestudio.swing.tree.OutlineRenderer" />
|
||||
</Tree>
|
||||
</ScrollPane>
|
||||
</Tab>
|
||||
</AdaptiveTabbedPane>
|
||||
<VBox id="leftVbox">
|
||||
<Panel layout="BorderLayout" id="leftPeerViewContainer" visible="false" />
|
||||
<AdaptiveTabbedPane id="leftTabPane" tabPlacement="JTabbedPane.LEFT" >
|
||||
<Tab id="participantsTab" name="participants" text="slides.participants" icon="participants.svg, 18" defaultTabType="AdaptiveTabType.PARTICIPANTS">
|
||||
<Panel id="participantsPanel" layout="BorderLayout">
|
||||
<ParticipantList id="participantList" constraints="BorderLayout.CENTER" />
|
||||
</Panel>
|
||||
</Tab>
|
||||
<Tab id="outlineTab" name="outline" text="menu.contents">
|
||||
<ScrollPane id="outlinePane">
|
||||
<Tree id="outlineTree" name="tree" focusable="false" rootVisible="false" showsRootHandles="true">
|
||||
<renderer class="org.lecturestudio.swing.tree.OutlineRenderer" />
|
||||
</Tree>
|
||||
</ScrollPane>
|
||||
</Tab>
|
||||
</AdaptiveTabbedPane>
|
||||
<Panel layout="BorderLayout" id="leftNoteSlideViewContainer" visible="false" />
|
||||
</VBox>
|
||||
<SlideView id="slideView" />
|
||||
</SplitPane>
|
||||
|
||||
|
@ -48,8 +52,11 @@
|
|||
</SplitPane>
|
||||
|
||||
<VBox id="rightVbox">
|
||||
<Panel layout="BorderLayout" id="peerViewContainer" visible="false" />
|
||||
<Panel layout="BorderLayout" id="rightPeerViewContainer" visible="false" />
|
||||
<AdaptiveTabbedPane id="rightTabPane" tabPlacement="JTabbedPane.RIGHT" defaultTabType="AdaptiveTabType.SLIDE" focusTraversable="false" />
|
||||
<Panel layout="BorderLayout" id="rightNoteSlideViewContainer" visible="false">
|
||||
<SlideView id="slideNotesView" />
|
||||
</Panel>
|
||||
</VBox>
|
||||
</SplitPane>
|
||||
</Panel>
|
||||
|
|
|
@ -11,6 +11,7 @@ slides.slide.preview = Folienvorschau
|
|||
slides.speech = Redebeitrag
|
||||
slides.currently.no.speech = Aktuell kein Redebeitrag
|
||||
slides.quiz.stop = Beenden
|
||||
slides.slide.notes = Notiz-Folien
|
||||
|
||||
speech.requested = hat sich gemeldet
|
||||
speech.accept = Annehmen
|
||||
|
|
|
@ -11,6 +11,7 @@ slides.slide.preview = Slides preview
|
|||
slides.speech = Speech
|
||||
slides.currently.no.speech = Currently no speach
|
||||
slides.quiz.stop = Stop
|
||||
slides.slide.notes = Slide notes
|
||||
|
||||
speech.requested = raised his hand
|
||||
speech.accept = Accept
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
<Separator type="t" defaultTool="true" />
|
||||
<Button id="prevSlideButton" icon="prev-slide-tool.svg, 24" tooltipText="toolbar.slide.prev.tooltip" />
|
||||
<Button id="nextSlideButton" icon="next-slide-tool.svg, 24" tooltipText="toolbar.slide.next.tooltip" />
|
||||
<Button id="nextBookmarkButton" icon="bookmark-next.svg, 24" tooltipText="toolbar.bookmark.next.tooltip" />
|
||||
<Button id="prevBookmarkButton" icon="bookmark-prev.svg, 24" tooltipText="toolbar.bookmark.prev.tooltip" />
|
||||
<Button id="newBookmarkButton" icon="bookmark-add.svg, 24" tooltipText="toolbar.bookmark.add.tooltip" tool="BOOKMARK" group="toolGroup" visible="false" />
|
||||
<ToolColorPickerButton id="customColorButton" accelerator="F1" group="colorGroup" />
|
||||
<ToggleButton id="colorButton1" accelerator="F2" group="colorGroup" defaultTool="true"/>
|
||||
<ToggleButton id="colorButton2" accelerator="F3" group="colorGroup" defaultTool="true" />
|
||||
|
@ -15,7 +18,7 @@
|
|||
<ToggleButton id="penButton" accelerator="P" icon="pen-tool.svg, 24" tooltipText="toolbar.pen.tooltip" tool="PEN" group="toolGroup" defaultTool="true" />
|
||||
<ToggleButton id="highlighterButton" accelerator="H" icon="highlighter-tool.svg, 24" tooltipText="toolbar.highlighter.tooltip" tool="HIGHLIGHTER" group="toolGroup" defaultTool="true" />
|
||||
<ToggleButton id="pointerButton" accelerator="A" icon="pointer-tool.svg, 24" tooltipText="toolbar.pointer.tooltip" tool="POINTER" group="toolGroup" defaultTool="true" />
|
||||
<ToggleButton id="textSelectButton" accelerator="S" icon="text-select-tool.svg, 24" tooltipText="toolbar.text.select.tooltip" tool="TEXT_SELECTION" group="toolGroup" defaultTool="true" />
|
||||
<ToggleButton id="textSelectButton" accelerator="V" icon="text-select-tool.svg, 24" tooltipText="toolbar.text.select.tooltip" tool="TEXT_SELECTION" group="toolGroup" defaultTool="true" />
|
||||
<ToggleButton id="lineButton" accelerator="I" icon="line-tool.svg, 24" tooltipText="toolbar.line.tooltip" tool="LINE" group="toolGroup" />
|
||||
<ToggleButton id="arrowButton" accelerator="W" icon="arrow-tool.svg, 24" tooltipText="toolbar.arrow.tooltip" tool="ARROW" group="toolGroup" />
|
||||
<ToggleButton id="rectangleButton" accelerator="R" icon="rectangle-tool.svg, 24" tooltipText="toolbar.rectangle.tooltip" tool="RECTANGLE" group="toolGroup" visible="false" />
|
||||
|
|
|
@ -27,6 +27,9 @@ toolbar.clone.tooltip = Kopier-Werkzeug ausw\u00E4hlen
|
|||
toolbar.erase.tooltip = Radiergummi ausw\u00E4hlen
|
||||
toolbar.latex.tooltip = LaTeX-Werkzeug ausw\u00E4hlen
|
||||
toolbar.text.tooltip = Textwerkzeug ausw\u00E4hlen
|
||||
toolbar.bookmark.prev.tooltip = Zu vorherigem Lesezeichen springen
|
||||
toolbar.bookmark.next.tooltip = Zu nächstem Lesezeichen springen
|
||||
toolbar.bookmark.add.tooltip = Lesezeichen hinzufügen
|
||||
toolbar.text.select.tooltip = Textauswahlwerkzeug ausw\u00E4hlen
|
||||
toolbar.clear.tooltip = L\u00F6sche alle Texte und Linien
|
||||
toolbar.extend.tooltip = Zeichenbereich erweitern
|
||||
|
|
|
@ -27,6 +27,9 @@ toolbar.clone.tooltip = Select copy tool
|
|||
toolbar.erase.tooltip = Select eraser
|
||||
toolbar.latex.tooltip = Select LaTeX tool
|
||||
toolbar.text.tooltip = Select text tool
|
||||
toolbar.bookmark.prev.tooltip = Jump to previous bookmark
|
||||
toolbar.bookmark.next.tooltip = Jump to next bookmark
|
||||
toolbar.bookmark.add.tooltip = Create bookmark
|
||||
toolbar.text.select.tooltip = Select text selection tool
|
||||
toolbar.clear.tooltip = Delete all annotations
|
||||
toolbar.extend.tooltip = Extend drawing area
|
||||
|
|
|
@ -46,6 +46,7 @@ public abstract class SwingApplication extends ApplicationBase implements Graphi
|
|||
|
||||
private JFrame window;
|
||||
|
||||
private MainPresenter<?> mainPresenter;
|
||||
|
||||
@Override
|
||||
protected void initInternal(String[] args) throws ExecutableException {
|
||||
|
@ -134,10 +135,7 @@ public abstract class SwingApplication extends ApplicationBase implements Graphi
|
|||
throw new ExecutableException(e);
|
||||
}
|
||||
|
||||
if (!OPEN_FILES.isEmpty()) {
|
||||
mainPresenter.openFile(OPEN_FILES.get(0));
|
||||
OPEN_FILES.clear();
|
||||
}
|
||||
this.mainPresenter = mainPresenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -164,6 +162,10 @@ public abstract class SwingApplication extends ApplicationBase implements Graphi
|
|||
catch (Exception e) {
|
||||
throw new ExecutableException(e);
|
||||
}
|
||||
if (!OPEN_FILES.isEmpty()) {
|
||||
mainPresenter.openFile(OPEN_FILES.get(0));
|
||||
OPEN_FILES.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.lecturestudio.swing.components;
|
||||
|
||||
import com.formdev.flatlaf.util.UIScale;
|
||||
|
||||
import org.lecturestudio.core.app.view.Screens;
|
||||
import org.lecturestudio.core.view.Screen;
|
||||
import org.lecturestudio.swing.AwtResourceLoader;
|
||||
|
@ -20,15 +21,25 @@ import java.util.function.Consumer;
|
|||
import static java.util.Objects.nonNull;
|
||||
|
||||
public class ExternalFrame extends JFrame {
|
||||
|
||||
private String name;
|
||||
|
||||
private Consumer<ExternalWindowPosition> positionChangedAction;
|
||||
|
||||
private Runnable closedAction;
|
||||
|
||||
private Consumer<Dimension> sizeChangedAction;
|
||||
|
||||
private String placeholderText;
|
||||
|
||||
private final Component body;
|
||||
|
||||
private final Component placeholder;
|
||||
|
||||
private boolean showBody = false;
|
||||
|
||||
public ExternalFrame(String name, Component body, Dimension minimumSize,
|
||||
Consumer<ExternalWindowPosition> positionChangedAction, Runnable closedAction,
|
||||
Consumer<Dimension> sizeChangedAction, String placeholderText) {
|
||||
|
||||
public ExternalFrame(String name, Component body, String placeholderText) {
|
||||
super(nonNull(name) ? name : "");
|
||||
|
||||
this.body = body;
|
||||
|
@ -42,26 +53,21 @@ public class ExternalFrame extends JFrame {
|
|||
|
||||
setIconImages(icons);
|
||||
|
||||
setMinimumSize(UIScale.scale(minimumSize));
|
||||
|
||||
if (nonNull(closedAction)) {
|
||||
addClosingListener(closedAction);
|
||||
|
||||
}
|
||||
|
||||
if (nonNull(positionChangedAction) || nonNull(sizeChangedAction)) {
|
||||
addMovedResizedListener(positionChangedAction, sizeChangedAction);
|
||||
}
|
||||
|
||||
addPlaceholder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinimumSize(Dimension minimumSize) {
|
||||
super.setMinimumSize(UIScale.scale(minimumSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean visible) {
|
||||
if (visible && showBody) {
|
||||
removePlaceholder();
|
||||
add(body);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
remove(body);
|
||||
addPlaceholder();
|
||||
}
|
||||
|
@ -73,6 +79,51 @@ public class ExternalFrame extends JFrame {
|
|||
}
|
||||
}
|
||||
|
||||
public void setClosedAction(Runnable closedAction) {
|
||||
this.closedAction = closedAction;
|
||||
|
||||
if (nonNull(closedAction)) {
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
if (nonNull(closedAction)) {
|
||||
closedAction.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setSizeChangedAction(Consumer<Dimension> sizeAction) {
|
||||
sizeChangedAction = sizeAction;
|
||||
|
||||
if (nonNull(sizeChangedAction)) {
|
||||
addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
if (nonNull(sizeChangedAction)) {
|
||||
sizeChangedAction.accept(e.getComponent().getSize());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setPositionChangedAction(Consumer<ExternalWindowPosition> positionAction) {
|
||||
positionChangedAction = positionAction;
|
||||
|
||||
if (nonNull(positionChangedAction) ) {
|
||||
addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
if (nonNull(positionChangedAction)) {
|
||||
externalComponentOpenedOrMoved(e, positionChangedAction);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void showBody() {
|
||||
if (showBody) {
|
||||
return;
|
||||
|
@ -86,7 +137,6 @@ public class ExternalFrame extends JFrame {
|
|||
repaint();
|
||||
}
|
||||
|
||||
|
||||
showBody = true;
|
||||
}
|
||||
|
||||
|
@ -106,10 +156,6 @@ public class ExternalFrame extends JFrame {
|
|||
showBody = false;
|
||||
}
|
||||
|
||||
public boolean isShowBody() {
|
||||
return showBody;
|
||||
}
|
||||
|
||||
private void addPlaceholder() {
|
||||
if (nonNull(placeholder)) {
|
||||
add(placeholder);
|
||||
|
@ -132,96 +178,10 @@ public class ExternalFrame extends JFrame {
|
|||
}
|
||||
}
|
||||
|
||||
private void addClosingListener(Runnable closedAction) {
|
||||
addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
if (nonNull(closedAction)) {
|
||||
closedAction.run();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void addMovedResizedListener(Consumer<ExternalWindowPosition> positionChangedAction,
|
||||
Consumer<Dimension> sizeChangedAction) {
|
||||
addComponentListener(new ComponentAdapter() {
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
if (nonNull(positionChangedAction)) {
|
||||
externalComponentOpenedOrMoved(e, positionChangedAction);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
if (nonNull(sizeChangedAction)) {
|
||||
sizeChangedAction.accept(e.getComponent().getSize());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void externalComponentOpenedOrMoved(ComponentEvent e, Consumer<ExternalWindowPosition> action) {
|
||||
final Point position = e.getComponent().getLocationOnScreen();
|
||||
final Screen screen = Screens.createScreen(e.getComponent().getGraphicsConfiguration().getDevice());
|
||||
|
||||
action.accept(new ExternalWindowPosition(screen, position));
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private String name;
|
||||
|
||||
private Component body;
|
||||
|
||||
private Dimension minimumSize = new Dimension(300, 300);
|
||||
|
||||
private Consumer<ExternalWindowPosition> positionChangedAction;
|
||||
|
||||
private Runnable closedAction;
|
||||
|
||||
private Consumer<Dimension> sizeChangedAction;
|
||||
|
||||
private String placeholderText;
|
||||
|
||||
public Builder setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setBody(Component body) {
|
||||
this.body = body;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setMinimumSize(Dimension minimumSize) {
|
||||
this.minimumSize = minimumSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPositionChangedAction(Consumer<ExternalWindowPosition> positionChangedAction) {
|
||||
this.positionChangedAction = positionChangedAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setClosedAction(Runnable closedAction) {
|
||||
this.closedAction = closedAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setSizeChangedAction(Consumer<Dimension> sizeChangedAction) {
|
||||
this.sizeChangedAction = sizeChangedAction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setPlaceholderText(String placeholderText) {
|
||||
this.placeholderText = placeholderText;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ExternalFrame build() {
|
||||
return new ExternalFrame(name, body, minimumSize, positionChangedAction, closedAction, sizeChangedAction,
|
||||
placeholderText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,8 @@ public class NotificationPane extends GlassPane {
|
|||
}
|
||||
|
||||
private void initialize() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
container = new JPanel(new GridBagLayout());
|
||||
container.setBorder(new EmptyBorder(20, 20, 20, 20));
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ import java.awt.event.ComponentAdapter;
|
|||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
@ -74,6 +76,8 @@ public class SlideView extends JComponent implements org.lecturestudio.core.view
|
|||
|
||||
private Page page;
|
||||
|
||||
private final PropertyChangeSupport changes = new PropertyChangeSupport(this);
|
||||
|
||||
private final Rectangle canvasBounds = new Rectangle();
|
||||
|
||||
private AffineTransform pageTransform = new AffineTransform();
|
||||
|
@ -114,6 +118,14 @@ public class SlideView extends JComponent implements org.lecturestudio.core.view
|
|||
renderPage();
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
changes.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
|
||||
changes.removePropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
public final void setAlignment(Position position) {
|
||||
if (alignment != position) {
|
||||
alignment = position;
|
||||
|
@ -362,6 +374,8 @@ public class SlideView extends JComponent implements org.lecturestudio.core.view
|
|||
imageRect.setSize(size.getWidth(), size.getHeight());
|
||||
|
||||
updateViewTransform();
|
||||
|
||||
changes.firePropertyChange("CanvasBounds", null, canvasBounds);
|
||||
}
|
||||
|
||||
private void initialize() {
|
||||
|
|
|
@ -455,6 +455,9 @@ public class ThumbPanel extends JPanel {
|
|||
if (selected) {
|
||||
g2d.setColor(Color.BLUE);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}else if(page.isOverlay()){
|
||||
g2d.setColor(Color.GRAY);
|
||||
g2d.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
else {
|
||||
g2d.setColor(getBackground());
|
||||
|
|
|
@ -6,6 +6,7 @@ public enum AdaptiveTabType {
|
|||
MESSAGE,
|
||||
SLIDE,
|
||||
PARTICIPANTS,
|
||||
NOTES
|
||||
NOTES,
|
||||
SLIDE_NOTES
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.lecturestudio.core.ExecutableBase;
|
|||
import org.lecturestudio.core.ExecutableException;
|
||||
import org.lecturestudio.core.geometry.Rectangle2D;
|
||||
import org.lecturestudio.core.model.Document;
|
||||
import org.lecturestudio.core.model.NotesPosition;
|
||||
import org.lecturestudio.core.model.Page;
|
||||
import org.lecturestudio.core.model.shape.Shape;
|
||||
import org.lecturestudio.core.pdf.PdfDocument;
|
||||
|
@ -221,6 +222,7 @@ public class PdfDocumentRenderer extends ExecutableBase {
|
|||
private void createPage(PresentationParameter param,
|
||||
Document newDocument, Page page) throws Exception {
|
||||
Rectangle2D pageRect = param.getPageRect();
|
||||
NotesPosition notesPosition = page.getDocument().getSplitSlideNotesPosition();
|
||||
|
||||
Page newPage = newDocument.createPage(page, pageScale ? pageRect : null);
|
||||
int pageIndex = newPage.getPageNumber();
|
||||
|
@ -237,11 +239,11 @@ public class PdfDocumentRenderer extends ExecutableBase {
|
|||
if (editable) {
|
||||
// Tag graphics stream to be able to find it later.
|
||||
graphics = (PDFGraphics2D) pdfDocument.createAppendablePageGraphics2D(
|
||||
pageIndex, PdfDocument.EMBEDDED_SHAPES_KEY);
|
||||
pageIndex, PdfDocument.EMBEDDED_SHAPES_KEY, NotesPosition.UNKNOWN);
|
||||
}
|
||||
else {
|
||||
graphics = (PDFGraphics2D) pdfDocument.createAppendablePageGraphics2D(
|
||||
pageIndex);
|
||||
pageIndex, NotesPosition.UNKNOWN);
|
||||
}
|
||||
|
||||
SwingGraphicsContext gc = new SwingGraphicsContext(graphics);
|
||||
|
@ -256,15 +258,18 @@ public class PdfDocumentRenderer extends ExecutableBase {
|
|||
}
|
||||
|
||||
AffineTransform annotTransform = transform.createInverse();
|
||||
Rectangle2D mediaBox = pdfDocument.getPageMediaBox(pageIndex);
|
||||
Rectangle2D mediaBox = pdfDocument.getPageMediaBox(pageIndex, notesPosition);
|
||||
|
||||
double pageWidth = mediaBox.getWidth();
|
||||
double sx = pageWidth * annotTransform.getScaleX();
|
||||
double tx = pageWidth * annotTransform.getTranslateX();
|
||||
double ty = pageWidth * annotTransform.getTranslateY();
|
||||
|
||||
// Move to top-left corner.
|
||||
gc.translate(-tx, ty + mediaBox.getHeight());
|
||||
if(page.getDocument().getActualSplitSlideNotesPosition() == NotesPosition.LEFT) {
|
||||
mediaBox.setRect(mediaBox.getWidth(), mediaBox.getY(), mediaBox.getWidth(), mediaBox.getHeight());
|
||||
tx -= pageWidth;
|
||||
}
|
||||
gc.translate(-tx , ty + mediaBox.getHeight());
|
||||
gc.scale(sx, -sx);
|
||||
|
||||
// Draw shapes.
|
||||
|
|
|
@ -73,6 +73,7 @@ public class ViewLoader<T extends Container> extends SwingEngine<T> {
|
|||
tagLibrary.registerTag("DisplayPanel", DisplayPanel.class);
|
||||
tagLibrary.registerTag("DocumentPreview", DocumentPreview.class);
|
||||
tagLibrary.registerTag("EllipseToolPreview", EllipseToolPreview.class);
|
||||
tagLibrary.registerTag("FormattedTextField", JFormattedTextField.class);
|
||||
tagLibrary.registerTag("IPTextField", IPTextField.class);
|
||||
tagLibrary.registerTag("LevelMeter", LevelMeter.class);
|
||||
tagLibrary.registerTag("LineToolPreview", LineToolPreview.class);
|
||||
|
|
|
@ -61,7 +61,9 @@ public class NotificationPopup extends JWindow {
|
|||
private final static String CONFIG_FILE = "resources/notification.properties";
|
||||
|
||||
private final Object lock = new Object();
|
||||
|
||||
|
||||
private final NotificationManager manager;
|
||||
|
||||
private final LinearGradientPaint gradient;
|
||||
|
||||
private final JTextArea messageLabel;
|
||||
|
@ -80,9 +82,7 @@ public class NotificationPopup extends JWindow {
|
|||
|
||||
private boolean pending;
|
||||
|
||||
private NotificationManager manager;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code NotificationPopup}.
|
||||
*
|
||||
|
@ -161,6 +161,8 @@ public class NotificationPopup extends JWindow {
|
|||
|
||||
height += 30;
|
||||
}
|
||||
|
||||
System.out.println(width + " " + height);
|
||||
|
||||
setAlwaysOnTop(true);
|
||||
setSize(width, height);
|
||||
|
|
|
@ -55,6 +55,8 @@ import org.lecturestudio.swing.util.SwingUtils;
|
|||
*/
|
||||
public class SwingNotificationPopupManager implements NotificationPopupManager {
|
||||
|
||||
private static final Dimension OFFSET = new Dimension(0, 55);
|
||||
|
||||
/** Visible notifications. */
|
||||
private final Map<Position, List<JWindow>> popupMap = new HashMap<>();
|
||||
|
||||
|
@ -102,7 +104,7 @@ public class SwingNotificationPopupManager implements NotificationPopupManager {
|
|||
return;
|
||||
}
|
||||
|
||||
popup.setLocation((int) location.getX(), (int) location.getY());
|
||||
popup.setLocation((int) location.getX() + OFFSET.width, (int) location.getY() + OFFSET.height);
|
||||
popup.setVisible(true);
|
||||
|
||||
addPopup(popup, position);
|
||||
|
@ -171,8 +173,7 @@ public class SwingNotificationPopupManager implements NotificationPopupManager {
|
|||
|
||||
private Point2D getLocation(Rectangle contentBounds, Rectangle rootBounds,
|
||||
Position position) {
|
||||
Point2D location = getInitialLocation(contentBounds, rootBounds,
|
||||
position);
|
||||
Point2D location = getInitialLocation(contentBounds, rootBounds, position);
|
||||
List<JWindow> popups = popupMap.get(position);
|
||||
|
||||
if (isNull(popups)) {
|
||||
|
|
Loading…
Reference in a new issue