devexpress-reporting
Version:
DevExpress Reporting provides the capability to develop a reporting application to create and customize reports.
401 lines (400 loc) • 17.6 kB
JavaScript
/**
* DevExpress HTML/JS Reporting (viewer\mobile\internal\gallery\_galleryModel.js)
* Version: 25.1.3
* Build date: Jun 26, 2025
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* License: https://www.devexpress.com/Support/EULAs/universal.xml
*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { getCurrentResolution } from '../../../internal/_utils';
import { previewDefaultResolution } from '../../../settings';
import { ZoomAutoBy } from '../../../constants';
import { BaseRenderingModel, createViewModelGenerator, mutable, mutableArray } from '@devexpress/analytics-core/analytics-serializer-native';
import { GalleryItem, GalleryItemBlock } from './_galleryItem';
export class GalleryModel extends BaseRenderingModel {
deferredUpdateViewModel() { return false; }
_createBlock(galleryItem, previewPage, className, visible) {
previewPage.disableResolutionReduction = true;
previewPage.maxZoom = 1;
const classSet = {};
if (this.animationEnabled && this.pageCount > 1) {
className && (classSet[className] = true);
classSet['dxrdp-animation'] = true;
}
return new GalleryItemBlock({
page: previewPage,
visible: visible,
classSet: classSet,
position: { top: 0, left: 0, width: 0, height: 0 },
reportPreview: galleryItem.preview
});
}
createViewModel() {
return createViewModelGenerator(super.createViewModel())
.generateProperty('animationEnabled', this.animationEnabled)
.generateProperty('selectedIndex', this.selectedIndex)
.generateProperty('items', this.items.map(x => x.getViewModel()))
.generateProperty('onOptionChanged', (event) => {
if (event.name === 'selectedIndex')
this.selectedIndex = event.value;
})
.getViewModel();
}
updateViewModel(args) {
const viewModel = this.getViewModel();
viewModel.selectedIndex = this.selectedIndex;
viewModel.animationEnabled = this.animationEnabled;
if (args.propertyName === 'items') {
viewModel.items = this.items.map(x => x.getViewModel());
}
}
onPropertyChanged(args) {
if (args.propertyName === 'selectedIndexReal') {
if (args.newValue >= 0) {
this.changePage(this.preview);
}
else if (args.newValue < 0) {
this.selectedIndexReal = 0;
}
}
else if (args.propertyName === 'selectedIndex') {
const result = args.newValue - args.oldValue;
if (result === -2 || result === 1) {
this.selectedIndexReal += 1;
}
else if (result === 2 || result === -1) {
this.selectedIndexReal -= 1;
}
}
if (args.propertyName === 'items' || args.propertyName === 'selectedIndex') {
this.updateContentSize();
}
}
updateContentSize() {
const currentItem = this.items[this.selectedIndex];
this._currentItemSubscriptionDispose && this._currentItemSubscriptionDispose();
this._currentItemSubscriptionDispose = currentItem.events.on('blocksChanged', (args) => {
_onCurrentItemBlocksChanged(currentItem.blocks);
});
let _currentBlockSubscriptions = [];
const _onCurrentItemBlocksChanged = (blocks) => {
const block = blocks && blocks[0];
_currentBlockSubscriptions.forEach(x => x());
_currentBlockSubscriptions = [];
if (!block) {
this.contentSize = { width: 'auto', height: 'auto' };
}
else {
_currentBlockSubscriptions.push(block.events.on('positionChanged', (args) => {
onBlockChanged();
}), block.page.events.on('sizeChanged', (args) => {
onBlockChanged();
}));
const onBlockChanged = () => {
const position = block.position;
const width = Math.max(position.width, block.page.size.width);
const height = Math.max(position.height, block.page.size.height);
this.contentSize = { width: width + 'px', height: height + 'px' };
};
onBlockChanged();
}
};
_onCurrentItemBlocksChanged(currentItem.blocks);
}
constructor(preview) {
super();
this.preview = preview;
this._spacing = 1;
this._animationTimeout = null;
this._currentItemSubscriptionDispose = null;
this._repaint = () => {
const args = { propertyName: 'repaint', newValue: {}, oldValue: {} };
this.events.call('propertyChanged', args);
};
this.horizontal = 1;
this.vertical = 1;
this.pageCount = 0;
const oldIndex = this.selectedIndex;
this.items = [
new GalleryItem(preview, this),
new GalleryItem(preview, this),
new GalleryItem(preview, this)
];
this.animationEnabled = preview.animationSettings.swipeEnabled;
const _calcHorizontalVertical = () => {
const _zoom = preview.originalZoom;
const pageHeight = Math.ceil(preview._pageHeight * getCurrentResolution(_zoom) / previewDefaultResolution());
const pageWidth = Math.ceil(preview._pageWidth * getCurrentResolution(_zoom) / previewDefaultResolution());
const _containerSize = preview.previewWrapperSize;
const horizontal = (preview.autoFitBy != ZoomAutoBy.PageWidth && (Math.floor(_containerSize.width / (pageWidth + 2 * this._spacing)))) || 1;
const vertical = Math.floor(_containerSize.height / (pageHeight + 2 * this._spacing)) || 1;
this.horizontal = horizontal;
this.vertical = vertical;
};
const updateGalleryContent = () => {
_calcHorizontalVertical();
this.pageCount = this.horizontal * this.vertical;
this.updateContent(preview, this.pageCount);
};
this.addDisposable(preview.events.on('previewWrapperSizeChanged', (args) => {
this.items.forEach(item => item.blocks.forEach(block => block.repaint = true));
updateGalleryContent();
const currentGalleryItem = this.items[this.selectedIndex];
this.updateBlocks(currentGalleryItem, this.pageCount, preview, this.selectedIndexReal, preview.animationSettings.zoomEnabled);
this._repaint();
}), preview.events.on('visiblePagesChanged', (args) => {
for (let i = 0; i < this.items.length; i++) {
this.items[i].blocks = [];
this.items[i].realIndex = -1;
}
updateGalleryContent();
}), preview.events.on('zoomUpdatingChanged', (args) => {
if (!args.newValue) {
clearTimeout(this.repaintTimeout);
this.repaintTimeout = setTimeout(() => this._repaint(), 410);
}
}), preview.events.on('originalZoomChanged', (args) => {
_calcHorizontalVertical();
const pageCount = this.horizontal * this.vertical;
if (this.pageCount !== pageCount) {
this.pageCount = pageCount;
this.items.forEach(item => item.blocks.forEach(block => block.repaint = true));
this.updateContent(preview, pageCount);
}
else if (this.pageCount === 1) {
const block = this.items[this.selectedIndex].blocks[0];
this.items.forEach((item, index) => {
if (index != this.selectedIndex)
item.blocks.forEach(block => block.repaint = true);
});
setTimeout(() => {
block.position = {
left: block.position.left,
top: block.position.top,
height: Math.max(this.preview.previewWrapperSize.height, block.page.size.height),
width: Math.max(this.preview.previewWrapperSize.width, block.page.size.width)
};
});
}
}), preview.events.on('pageIndexChanged', (args) => {
updateGalleryContent();
}));
this.getSwipeLeftEnabled = () => {
return this.selectedIndexReal !== 0;
};
this.getSwipeRightEnabled = () => {
return this.selectedIndexReal != (Math.ceil(preview.visiblePages.length / (this.horizontal * this.vertical)) - 1);
};
}
dispose() {
clearTimeout(this.repaintTimeout);
super.dispose();
}
updatePagesVisible(preview) {
if (this.items[this.selectedIndex]) {
let someActive = false;
const pages = this.items[this.selectedIndex].blocks;
if (pages.length > 0) {
for (let i = 0; i < pages.length; i++) {
if (pages[i].page) {
pages[i].page.isClientVisible = true;
if (pages[i].page.active) {
someActive = true;
}
}
}
if (!someActive) {
pages[0].page && preview.goToPage(pages[0].page.pageIndex);
}
}
}
}
updateCurrentBlock() {
if (this.items[this.selectedIndex]) {
const blocks = this.items[this.selectedIndex].blocks;
if (blocks.length > 0) {
if (blocks.length > 1) {
this.currentBlockText = [blocks[0].page.pageIndex + 1, blocks[blocks.length - 1].page.pageIndex + 1].join(' - ');
}
else {
if (blocks[0].page) {
this.currentBlockText = (this.preview.pageIndex + 1).toString();
}
}
}
}
}
updateContent(preview, pagesCount) {
const itemsCount = Math.ceil(preview.visiblePages.length / pagesCount);
let pageIndex = 0;
let isCurrentBlock = false;
let realIndex = 0;
for (let i = 0; i < itemsCount; i++) {
for (let j = 0; j < pagesCount; j++) {
if (preview.visiblePages[pageIndex].active) {
isCurrentBlock = true;
realIndex = i;
break;
}
pageIndex++;
if (preview.visiblePages.length === pageIndex) {
break;
}
}
if (isCurrentBlock)
break;
}
if (this.selectedIndexReal !== realIndex) {
this.selectedIndexReal = realIndex;
}
else {
this.changePage(preview);
}
}
updateBlockPositions(blocks, visible) {
const height = this.preview.previewWrapperSize.height / this.vertical;
const width = this.preview.previewWrapperSize.width / this.horizontal;
for (let i = 0; i < blocks.length; i++) {
const vertical = Math.floor((i) / this.horizontal);
const horizontal = i - (this.horizontal * vertical);
const left = horizontal * width;
if (blocks[i].visible === visible || blocks[i].visible === true) {
blocks[i].position = {
top: vertical * height,
left: left,
width: width,
height: height
};
blocks[i].visible = true;
}
else {
blocks[i].position = {
top: vertical * height,
left: blocks[i].classSet['left'] ? ((this.preview.previewWrapperSize.width + left) * -1) : this.preview.previewWrapperSize.width + left,
width: width,
height: height
};
}
}
}
updateStartBlocks(galleryItem, pages) {
const currentBlockPages = galleryItem.blocks.map(x => x.page);
let firstPage = pages.indexOf(currentBlockPages[0]);
if (firstPage !== -1) {
for (let i = 0; i < firstPage; i++) {
galleryItem.blocks.splice(i, 0, this._createBlock(galleryItem, pages[i], 'left', false));
}
}
else {
firstPage = currentBlockPages.indexOf(pages[0]);
if (firstPage !== -1) {
galleryItem.blocks.splice(0, firstPage);
}
}
return firstPage;
}
updateLastBlocks(galleryItem, pages) {
const currentBlockPages = galleryItem.blocks.map(x => x.page);
let lastPage = pages.indexOf(currentBlockPages[currentBlockPages.length - 1]);
if (lastPage !== -1) {
for (let i = lastPage + 1; i < pages.length; i++) {
galleryItem.blocks.splice(i, 0, this._createBlock(galleryItem, pages[i], 'right', false));
}
}
else {
lastPage = currentBlockPages.indexOf(pages[pages.length - 1]);
galleryItem.blocks.splice(lastPage + 1, currentBlockPages.length - lastPage);
}
return lastPage;
}
updateBlocks(galleryItem, pagesCount, preview, index, useAnimation = false) {
const blocks = galleryItem.blocks;
if (galleryItem.realIndex !== index
|| (blocks.length !== pagesCount || blocks[0].page.pageIndex === -1)
|| blocks.some(x => x.repaint)) {
galleryItem.realIndex = index;
clearTimeout(this._animationTimeout);
const startIndex = pagesCount * index;
if (startIndex < 0 || startIndex >= preview.visiblePages.length) {
galleryItem.blocks = [];
return;
}
const pages = [];
for (let i = startIndex; i < startIndex + pagesCount; i++) {
if (i >= preview.visiblePages.length) {
break;
}
pages.push(preview.visiblePages[i]);
}
const first = this.updateStartBlocks(galleryItem, pages);
const last = this.updateLastBlocks(galleryItem, pages);
if (first === -1 && last === -1) {
galleryItem.blocks = [];
for (let i = 0; i < pages.length; i++) {
galleryItem.blocks.splice(i, 0, this._createBlock(galleryItem, pages[i], null, true));
}
}
this.updateBlockPositions(galleryItem.blocks, true);
const self = this;
if (useAnimation) {
this._animationTimeout = setTimeout(() => {
!self.isDisposing && self.updateBlockPositions(galleryItem.blocks, false);
}, 400);
}
else {
self.updateBlockPositions(galleryItem.blocks, false);
}
}
}
changePage(preview) {
const pagesCount = this.horizontal * this.vertical;
const itemsCount = Math.ceil(preview.visiblePages.length / pagesCount);
if (this.selectedIndex === this.items.length - 1) {
this.updateBlocks(this.items[0], pagesCount, preview, this.selectedIndexReal + 1);
this.updateBlocks(this.items[1], pagesCount, preview, this.selectedIndexReal - 1);
}
else if (this.selectedIndex === 0) {
this.updateBlocks(this.items[2], pagesCount, preview, this.selectedIndexReal - 1);
this.updateBlocks(this.items[1], pagesCount, preview, this.selectedIndexReal + 1);
}
else {
this.updateBlocks(this.items[0], pagesCount, preview, this.selectedIndexReal - 1);
this.updateBlocks(this.items[2], pagesCount, preview, this.selectedIndexReal + 1);
}
const currentGalleryItem = this.items[this.selectedIndex];
this.updateBlocks(currentGalleryItem, pagesCount, preview, this.selectedIndexReal, preview.animationSettings.zoomEnabled);
if (!this.isAnimated) {
this.updatePagesVisible(preview);
}
this.updateCurrentBlock();
}
}
__decorate([
mutable(() => { })
], GalleryModel.prototype, "repaint", void 0);
__decorate([
mutable(null)
], GalleryModel.prototype, "repaintTimeout", void 0);
__decorate([
mutable(false)
], GalleryModel.prototype, "isAnimated", void 0);
__decorate([
mutableArray(() => [])
], GalleryModel.prototype, "items", void 0);
__decorate([
mutable('')
], GalleryModel.prototype, "currentBlockText", void 0);
__decorate([
mutable(0)
], GalleryModel.prototype, "selectedIndexReal", void 0);
__decorate([
mutable(0)
], GalleryModel.prototype, "selectedIndex", void 0);
__decorate([
mutable(false)
], GalleryModel.prototype, "animationEnabled", void 0);