From 76832ef7502eb4b6db79b7251bd3459c2798aa8d Mon Sep 17 00:00:00 2001
From: jojohoch <joachim.hoch@iqb.hu-berlin.de>
Date: Thu, 13 Jan 2022 19:01:12 +0100
Subject: [PATCH] [player] Calculate centering of layout

Fixed-width pages are always centered in the browser, even if the
specified percentage is not equal to 50%.

The percentage weighting of the pages has an effect if the width of the
pages is greater than the width of the browser window.
---
 docs/release-notes-player.txt                 |  3 ++
 .../app/components/layout/layout.component.ts | 47 ++++++++++++++++---
 .../src/app/services/native-event.service.ts  |  8 ++++
 3 files changed, 51 insertions(+), 7 deletions(-)

diff --git a/docs/release-notes-player.txt b/docs/release-notes-player.txt
index b99419644..b3dd555e9 100644
--- a/docs/release-notes-player.txt
+++ b/docs/release-notes-player.txt
@@ -1,5 +1,8 @@
 Player
 ======
+next
+- Improve the centering of the layout
+
 1.15.0
 - Fix restoring of toggle buttons
 - Prevent audio/video hint text from being displayed after reloading a played audio/video file
diff --git a/projects/player/src/app/components/layout/layout.component.ts b/projects/player/src/app/components/layout/layout.component.ts
index 412791e27..93988dec8 100644
--- a/projects/player/src/app/components/layout/layout.component.ts
+++ b/projects/player/src/app/components/layout/layout.component.ts
@@ -1,10 +1,12 @@
 import {
+  AfterViewInit, ChangeDetectorRef,
   Component, EventEmitter, Input, OnDestroy, OnInit, Output
 } from '@angular/core';
 import { FormGroup } from '@angular/forms';
-import { TranslateService } from '@ngx-translate/core';
 import { Subject } from 'rxjs';
 import { takeUntil } from 'rxjs/operators';
+import { TranslateService } from '@ngx-translate/core';
+import { NativeEventService } from '../../services/native-event.service';
 import { PlayerConfig } from '../../models/verona';
 import { Page } from '../../../../../common/models/page';
 
@@ -13,7 +15,7 @@ import { Page } from '../../../../../common/models/page';
   templateUrl: './layout.component.html',
   styleUrls: ['./layout.component.css']
 })
-export class LayoutComponent implements OnInit, OnDestroy {
+export class LayoutComponent implements OnInit, AfterViewInit, OnDestroy {
   @Input() parentForm!: FormGroup;
   @Input() pages!: Page[];
   @Input() selectedIndex!: number;
@@ -47,7 +49,10 @@ export class LayoutComponent implements OnInit, OnDestroy {
   containerMaxWidth: { alwaysVisiblePage: string, scrollPages: string } =
   { alwaysVisiblePage: '0px', scrollPages: '0px' };
 
-  constructor(private translateService: TranslateService) { }
+  constructor(private translateService: TranslateService,
+              private nativeEventService: NativeEventService,
+              private changeDetectorRef: ChangeDetectorRef) {
+  }
 
   ngOnInit(): void {
     this.initPages();
@@ -57,6 +62,38 @@ export class LayoutComponent implements OnInit, OnDestroy {
       .subscribe((selectedIndex: number): void => { this.selectedIndex = selectedIndex; });
   }
 
+  ngAfterViewInit(): void {
+    if (this.alwaysVisiblePage &&
+      this.alwaysVisiblePage.hasMaxWidth &&
+      this.layoutAlignment === 'row') {
+      this.nativeEventService.resize.pipe(takeUntil(this.ngUnsubscribe))
+        .subscribe((windowWidth: number): void => this.calculateMargin(windowWidth));
+      this.calculateMargin(window.innerWidth);
+    }
+  }
+
+  onSelectedIndexChange(selectedIndex: number): void {
+    this.selectedIndexChange.emit(selectedIndex);
+  }
+
+  private calculateMargin(windowWidth:number): void {
+    if (this.alwaysVisiblePage) {
+      if (windowWidth > this.maxWidth.alwaysVisiblePage + this.maxWidth.scrollPages) {
+        const margin = (windowWidth - (
+          this.maxWidth.alwaysVisiblePage +
+          this.maxWidth.scrollPages
+        )) / 2;
+        this.aspectRatioRow.alwaysVisiblePage = (100 / windowWidth) * (margin + this.maxWidth.alwaysVisiblePage);
+      } else {
+        let pageWidth = (this.alwaysVisiblePage.alwaysVisibleAspectRatio / 100) * windowWidth;
+        pageWidth = pageWidth > this.maxWidth.alwaysVisiblePage ? this.maxWidth.alwaysVisiblePage : pageWidth;
+        this.aspectRatioRow.alwaysVisiblePage = (pageWidth / windowWidth) * 100;
+      }
+      this.aspectRatioRow.scrollPages = 100 - this.aspectRatioRow.alwaysVisiblePage;
+      this.changeDetectorRef.detectChanges();
+    }
+  }
+
   private initPages(): void {
     this.alwaysVisibleUnitPageIndex = this.pages.findIndex((page: Page): boolean => page.alwaysVisible);
     this.alwaysVisiblePage = this.pages[this.alwaysVisibleUnitPageIndex];
@@ -122,10 +159,6 @@ export class LayoutComponent implements OnInit, OnDestroy {
 
   private getAbsolutePageWidth = (page: Page | undefined): number => ((page) ? 2 * page.margin + page.maxWidth : 0);
 
-  onSelectedIndexChange(selectedIndex: number): void {
-    this.selectedIndexChange.emit(selectedIndex);
-  }
-
   ngOnDestroy(): void {
     this.ngUnsubscribe.next();
     this.ngUnsubscribe.complete();
diff --git a/projects/player/src/app/services/native-event.service.ts b/projects/player/src/app/services/native-event.service.ts
index b3c456ca9..84d447949 100644
--- a/projects/player/src/app/services/native-event.service.ts
+++ b/projects/player/src/app/services/native-event.service.ts
@@ -11,6 +11,7 @@ import { mergeMap } from 'rxjs/operators';
 export class NativeEventService {
   private _focus = new Subject<boolean>();
   private _mouseUp = new Subject<Event>();
+  private _resize = new Subject<number>();
 
   constructor(@Inject(DOCUMENT) private document: Document) {
     from(['blur', 'focus'])
@@ -25,6 +26,9 @@ export class NativeEventService {
       .subscribe((mouseEvent: Event) => {
         this._mouseUp.next(mouseEvent);
       });
+
+    fromEvent(window, 'resize')
+      .subscribe(() => this._resize.next(window.innerWidth));
   }
 
   get focus(): Observable<boolean> {
@@ -34,4 +38,8 @@ export class NativeEventService {
   get mouseUp(): Observable<Event> {
     return this._mouseUp.asObservable();
   }
+
+  get resize(): Observable<number> {
+    return this._resize.asObservable();
+  }
 }
-- 
GitLab