Web Components Dock Manager Desktop Integration
O componente Infragistics Web Components Dock Manager pode ser usado em um aplicativo de desktop Electron de várias janelas para gerenciar o layout de cada janela, arrastar painéis para fora de uma janela para criar uma nova janela e arrastar/soltar painéis de uma janela para outra. Você pode encontrar um exemplo de implementação desse aplicativo no repositório a seguir https://github.com/IgniteUI/dock-manager-electron-app.
Implementation
Vamos passar pelas partes mais importantes da implementação deste aplicativo.
Project Structure
Usamos a ferramenta Electron Forge CLI e seu modelo Typescript + Webpack para criar um aplicativo Electron. O Electron tem dois tipos de processos: Main e Renderer.
- O processo Main cria páginas da Web criando instâncias de BrowserWindow. Cada instância de BrowserWindow executa a página da Web em seu processo de renderização.
- O processo do Renderizador gerencia apenas a página da Web correspondente.
O script index.ts especifica o ponto de entrada do aplicativo Electron que executará o processo Main. A maior parte do código do nosso aplicativo está dentro do arquivo renderer.ts que é executado no processo Renderer. O index.html representa o conteúdo da página da web. Os estilos da página da Web são hospedados no arquivo index.css.
Dock Manager Setup
Depois de instalar o pacote do Dock Manager, registramos o componente do Dock Manager usando o defineCustomElements() no arquivo renderer.ts. Isso permite adicionar o
Para o conteúdo do painel do Dock Manager, usamos elementos iframe que hospedam URLs diferentes. No nosso caso, esses urls apontam para Ignite UI for Angular exemplos. Como os elementos iframe são independentes, movê-los de uma janela para outra é facilmente realizado.
Drag and drop
Para oferecer suporte ao arrastar painéis para fora da janela do aplicativo, substituímos o arrastar / soltar interno que cria painéis flutuantes no aplicativo por uma implementação personalizada com base na API HTML Drag and Drop. Assinamos os PaneHeaderConnected
eventos and TabHeaderConnected
que são disparados quando um elemento de cabeçalho é conectado ao DOM. Quando um elemento de cabeçalho é conectado, redefinimos os ouvintes internos dragService
e de anexação DragStart
e DragEnd
eventos.
const paneHeaderConnected = (event: CustomEvent<IgcPaneHeaderConnectionEventArgs>) => {
const element = event.detail.element;
element.dragService.destroy();
element.dragService = null;
element.draggable = true;
element.ondragstart = ev => {
paneHeaderDragStart(event.detail.pane, ev);
};
element.ondragend = ev => {
paneHeaderDragEnd(ev);
};
}
dockManager.addEventListener('paneHeaderConnected', paneHeaderConnected);
PaneHeaderDragStart
Na função, definimos a draggedPane
propriedade do componente Dock Manager, que o notificará de que uma operação de arrastar foi iniciada.
const paneHeaderDragStart = async (pane: IgcContentPane, event: DragEvent) => {
event.dataTransfer.dropEffect = 'move';
dockManager.draggedPane = pane;
// ...
}
Nós nos inscrevemos nos DragOver
eventos and drop
do document
elemento. DragOver
No ouvinte, notificamos o Dock Manager de que o mouse é arrastado sobre ele definindo sua dropPosition
propriedade). Isso força o Dock Manager a exibir seus indicadores de encaixe.
const handleDocumentDragOver = (event: DragEvent) => {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
dockManager.dropPosition = {
x: event.clientX,
y: event.clientY
};
}
document.addEventListener('dragover', handleDocumentDragOver);
document.addEventListener('drop', handleDocumentDrop);
paneHeaderDragEnd
Na função, detectamos se o painel foi descartado fora da janela do aplicativo e chamamos a droppedOutOfWindow
função.
const paneHeaderDragEnd = async (event: DragEvent) => {
event.preventDefault();
// ...
// dropped outside of the application
if (event.dataTransfer.dropEffect === 'none') {
await droppedOutOfWindow(event);
}
// ...
}
Quando o cabeçalho do painel é solto dentro de um documento, chamamos o DropPane
método que notifica o Dock Manager de que o painel arrastado foi descartado. Se o painel foi descartado em um indicador de encaixe, o método retornará true. Se o painel foi solto na mesma janela da qual foi arrastado, o painel será encaixado em sua nova posição automaticamente. No entanto, se ele foi descartado em outra janela, chamamos a droppedInAnotherWindow
função que primeiro remove o painel do Dock Manager de origem e, em seguida, o adiciona ao novo.
const handleDocumentDrop = async (event: DragEvent) => {
const contentId = (dockManager.draggedPane as IgcContentPane).contentId;
const docked = await dockManager.dropPane();
if (docked) {
const contentElement = dockManager.querySelector('[slot=' + contentId + ']');
// if the content element is missing from the current dock manager it means it comes from another window
if (!contentElement) {
await droppedInAnotherWindow();
}
}
}
Quando um painel é removido de sua janela atual, precisamos removê-lo draggedPane
de seu componente Dock Manager e atualizar o layout.
const draggedPane = dockManager.draggedPane as IgcContentPane;
await dockManager.removePane(draggedPane);
dockManager.layout = { ...dockManager.layout };
Em seguida, precisamos mover o elemento de conteúdo do painel para sua nova janela. Para isso, usamos o método document.adoptNode(), que nos permite transferir o nó do elemento de conteúdo para o novo documento e, finalmente, anexá-lo como filho do novo componente do Dock Manager.
const contentElement = dockManager.querySelector('[slot=' + draggedPane.contentId + ']');
const newDocument = childWindow.document;
const newDockManager = newDocument.getElementById('dockManager') as IgcDockManagerComponent;
const adoptedNode = newDocument.adoptNode(contentElement);
newDockManager.appendChild(adoptedNode);
Window Management
Estamos usando o método nativo window.open() para abrir uma nova janela no processo do Renderizador. Definimos a nativeWindowOpen
opção como true ao criar o BrowserWindow
no index.ts. Isso nos dá acesso direto ao objeto filho Window
e seu. document
Você pode ler mais sobre como abrir janelas do processo Renderer neste tópico do Electron. Observe que a nativeWindowOpen
opção ainda é experimental.
mainWindow = new BrowserWindow({
height: 800,
width: 1000,
webPreferences: {
nativeWindowOpen: true
}
});
Nesta aplicação, implementamos um IDockManagerWindow
tipo que pode ser uma janela principal (IMainDockManagerWindow
) ou uma janela filha (IChildDockManagerWindow
). A janela principal é aquela criada quando o aplicativo é iniciado. Ele contém referências a todas as suas janelas filho. Uma janela filho é criada quando um painel é solto de uma janela e tem uma referência à janela principal do aplicativo.
Para obter o código-fonte completo, clone o repositório.