Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 94 additions & 8 deletions packages/base/src/mainview/mainView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ import {
VectorTile as VectorTileLayer,
WebGLTile as WebGlTileLayer
} from 'ol/layer';
import BaseLayer from 'ol/layer/Base';
import TileLayer from 'ol/layer/Tile';
import { fromLonLat, toLonLat, transformExtent } from 'ol/proj';
import {
fromLonLat,
get as getRegisteredProjection,
toLonLat,
transformExtent
} from 'ol/proj';
import Feature from 'ol/render/Feature';
import {
GeoTIFF as GeoTIFFSource,
Expand Down Expand Up @@ -96,9 +100,6 @@ export class MainView extends React.Component<IProps, IStates> {
constructor(props: IProps) {
super(props);

proj4.defs(Array.from(proj4list));
register(proj4);

this._mainViewModel = this.props.viewModel;
this._mainViewModel.viewSettingChanged.connect(this._onViewChanged, this);

Expand Down Expand Up @@ -133,6 +134,7 @@ export class MainView extends React.Component<IProps, IStates> {
};

this._sources = [];
this._loadingLayers = new Set();
this._commands = new CommandRegistry();
this._contextMenu = new ContextMenu({ commands: this._commands });
}
Expand Down Expand Up @@ -749,7 +751,7 @@ export class MainView extends React.Component<IProps, IStates> {
private async _buildMapLayer(
id: string,
layer: IJGISLayer
): Promise<BaseLayer | undefined> {
): Promise<Layer | undefined> {
const sourceId = layer.parameters?.source;
const source = this._model.sharedModel.getLayerSource(sourceId);
if (!source) {
Expand All @@ -760,6 +762,8 @@ export class MainView extends React.Component<IProps, IStates> {
await this.addSource(sourceId, source, id);
}

this._loadingLayers.add(id);

let newMapLayer;
let layerParameters;

Expand Down Expand Up @@ -842,15 +846,52 @@ export class MainView extends React.Component<IProps, IStates> {
}
}

await this._waitForSourceReady(newMapLayer);

// OpenLayers doesn't have name/id field so add it
newMapLayer.set('id', id);

// we need to keep track of which source has which layers
this._sourceToLayerMap.set(layerParameters.source, id);

this.addProjection(newMapLayer);

this._loadingLayers.delete(id);

return newMapLayer;
}

addProjection(newMapLayer: Layer) {
const sourceProjection = newMapLayer.getSource()?.getProjection();
if (!sourceProjection) {
console.warn('Layer source projection is undefined or invalid');
return;
}

const projectionCode = sourceProjection.getCode();

const isProjectionRegistered = getRegisteredProjection(projectionCode);
if (!isProjectionRegistered) {
// Check if the projection exists in proj4list
if (!proj4list[projectionCode]) {
console.warn(
`Projection code '${projectionCode}' not found in proj4list`
);
return;
}

try {
proj4.defs([proj4list[projectionCode]]);
register(proj4);
} catch (error: any) {
console.warn(
`Failed to register projection '${projectionCode}'. Error: ${error.message}`
);
return;
}
}
}

/**
* Add a layer to the map.
*
Expand All @@ -866,6 +907,8 @@ export class MainView extends React.Component<IProps, IStates> {

const newMapLayer = await this._buildMapLayer(id, layer);
if (newMapLayer !== undefined) {
await this._waitForReady();

this._Map.getLayers().insertAt(index, newMapLayer);
}
}
Expand Down Expand Up @@ -996,7 +1039,7 @@ export class MainView extends React.Component<IProps, IStates> {
async updateLayer(
id: string,
layer: IJGISLayer,
mapLayer: BaseLayer
mapLayer: Layer
): Promise<void> {
const sourceId = layer.parameters?.source;
const source = this._model.sharedModel.getLayerSource(sourceId);
Expand Down Expand Up @@ -1057,6 +1100,48 @@ export class MainView extends React.Component<IProps, IStates> {
}
}

/**
* Wait for all layers to be loaded.
*/
private _waitForReady(): Promise<void> {
return new Promise(resolve => {
const checkReady = () => {
if (this._loadingLayers.size === 0) {
resolve();
} else {
setTimeout(checkReady, 50);
}
};

checkReady();
});
}

/**
* Wait for a layers source state to be 'ready'
* @param layer The Layer to check
*/
private _waitForSourceReady(layer: Layer) {
return new Promise<void>((resolve, reject) => {
const checkState = () => {
const state = layer.getSourceState();
if (state === 'ready') {
layer.un('change', checkState);
resolve();
} else if (state === 'error') {
layer.un('change', checkState);
reject(new Error('Source failed to load.'));
}
};

// Listen for state changes
layer.on('change', checkState);

// Check the state immediately in case it's already 'ready'
checkState();
});
}

/**
* Remove a layer from the map.
*
Expand Down Expand Up @@ -1226,7 +1311,7 @@ export class MainView extends React.Component<IProps, IStates> {
return this._Map
.getLayers()
.getArray()
.find(layer => layer.get('id') === id);
.find(layer => layer.get('id') === id) as Layer;
}

/**
Expand Down Expand Up @@ -1600,4 +1685,5 @@ export class MainView extends React.Component<IProps, IStates> {
private _sourceToLayerMap = new Map();
private _documentPath?: string;
private _contextMenu: ContextMenu;
private _loadingLayers: Set<string>;
}
Loading