Web Components Dock Manager Desktop Integration

    Infragistics Web Components Dock Manager 구성 요소는 다중 창 Electron 데스크톱 응용 프로그램에서 각 창의 레이아웃을 관리하고, 새 창을 생성하기 위해 창 외부로 창을 끌어서 한 창에서 다른 창으로 창을 끌어서 놓기 위해 사용할 수 있습니다. 다음 저장소 https://github.com/IgniteUI/dock-manager-electron-app에서 이러한 애플리케이션의 샘플 구현을 찾을 수 있습니다.

    Web Components Dock Manager desktop integration

    Implementation

    이 애플리케이션 구현의 가장 중요한 부분을 살펴보겠습니다.

    Project Structure

    Electron Forge CLI 도구와 해당 Typescript + Webpack 템플릿을 사용하여 Electron 애플리케이션을 만들었습니다. Electron에는 Main과 Renderer라는 두 가지 프로세스가 있습니다.

    • Main 프로세스는 BrowserWindow 인스턴스를 생성하여 웹 페이지를 생성합니다. 각 BrowserWindow 인스턴스는 렌더러 프로세스에서 웹 페이지를 실행합니다.
    • 렌더러 프로세스는 해당 웹 페이지만 관리합니다.

    index.ts 스크립트는 Main 프로세스를 실행할 Electron 애플리케이션의 진입점을 지정합니다. 우리 애플리케이션의 코드 대부분은 렌더러 프로세스에서 실행되는 renderer.ts 파일 내에 있습니다. index.html은 웹페이지의 내용을 나타냅니다. 웹 페이지의 스타일은 index.css 파일에서 호스팅됩니다.

    Dock Manager Setup

    Dock Manager 패키지를 설치한 후 renderer.ts 파일의 DefineCustomElements()를 사용하여 Dock Manager 구성 요소를 등록했습니다. 이를 통해 다음을 추가할 수 있습니다.index.html 파일에 있습니다.

    Dock Manager 창 콘텐츠의 경우 다양한 URL을 호스팅하는 iframe 요소를 사용했습니다. 우리의 경우 이러한 URL은 Ignite UI for Angular 가리킵니다. iframe 요소는 독립적이므로 한 창에서 다른 창으로 쉽게 이동할 수 있습니다.

    Drag and drop

    애플리케이션 창 외부에서 창 드래그를 지원하기 위해 애플리케이션 내 부동 창을 생성하는 내장된 드래그/드롭을 HTML 드래그 앤 드롭 API를 기반으로 한 사용자 정의 구현으로 대체했습니다. 헤더 요소가 DOM에 연결될 때 발생하는 PaneHeaderConnectedTabHeaderConnected 이벤트를 구독했습니다. 헤더 요소가 연결되면 내장된 dragService 재설정하고 DragStartDragEnd 이벤트 리스너를 연결합니다.

    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 함수에서 드래그 작업이 시작되었음을 알리는 Dock Manager 구성 요소의 draggedPane 속성을 설정합니다.

    const paneHeaderDragStart = async (pane: IgcContentPane, event: DragEvent) => {
        event.dataTransfer.dropEffect = 'move';
        dockManager.draggedPane = pane;
        // ...
    }
    

    document 요소의 DragOverdrop 이벤트를 구독했습니다. DragOver 리스너에서는 dropPosition 속성을 설정하여 Dock 관리자에 마우스가 드래그되었음을 알립니다. 이렇게 하면 Dock Manager가 도킹 표시기를 표시하게 됩니다.

    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 함수에서는 창이 응용 프로그램 창 외부에 놓였는지 감지하고 droppedOutOfWindow 함수를 호출합니다.

    const paneHeaderDragEnd = async (event: DragEvent) => {
        event.preventDefault();
        // ...
    
        // dropped outside of the application
        if (event.dataTransfer.dropEffect === 'none') {
            await droppedOutOfWindow(event);
        }
        // ...
    }
    

    창 헤더가 문서 내부에 놓이면 드래그된 창이 삭제되었음을 Dock 관리자에 알리는 DropPane 메서드를 호출합니다. 창이 도킹 표시기에 놓인 경우 메서드는 true 를 반환합니다. 창을 끌어온 동일한 창에 놓으면 창이 자동으로 새 위치에 도킹됩니다. 그러나 다른 창에 놓으면 먼저 소스 Dock Manager에서 창을 제거한 다음 새 창에 추가하는 droppedInAnotherWindow 함수를 호출합니다.

    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();
            }
        }
    }
    

    창이 현재 창에서 삭제되면 Dock Manager 구성 요소에서 draggedPane 제거하고 레이아웃을 업데이트해야 합니다.

    const draggedPane = dockManager.draggedPane as IgcContentPane;
    await dockManager.removePane(draggedPane);
    dockManager.layout = { ...dockManager.layout };
    

    다음으로 창 콘텐츠 요소를 새 창으로 이동해야 합니다. 이를 위해 document.adoptNode() 메서드를 사용합니다. 이를 통해 콘텐츠 요소 노드를 새 문서로 전송하고 마지막으로 새 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

    우리는 네이티브를 사용하고 있습니다 창.열기() 렌더러 프로세스에서 새 창을 여는 방법입니다. 우리는 nativeWindowOpen 옵션 진실 생성할 때 BrowserWindow에서 index.ts. 이를 통해 우리는 아이에게 직접 접근할 수 있습니다. Window 객체와 그 document. 이 Electron에서 렌더러 프로세스에서 창을 여는 방법에 대해 자세히 알아볼 수 있습니다. 주제. 참고하시기 바랍니다 nativeWindowOpen 옵션은 아직 실험적입니다.

    mainWindow = new BrowserWindow({
        height: 800,
        width: 1000,
        webPreferences: {
            nativeWindowOpen: true
        }
    });
    

    이 응용 프로그램에서는 기본 창(IMainDockManagerWindow) 또는 하위 창(IChildDockManagerWindow)이 될 수 있는 IDockManagerWindow 유형을 구현했습니다. 메인 윈도우는 애플리케이션이 시작될 때 생성되는 윈도우입니다. 여기에는 모든 하위 창에 대한 참조가 포함되어 있습니다. 하위 창은 창이 창 밖으로 나올 때 생성되며 애플리케이션의 기본 창에 대한 참조를 갖습니다.

    전체 소스 코드를 보려면 저장소를 복제하세요.

    API References