[Eclipse] 실전 플러그인 개발: JFace와 가까워지기

Ma_Seokjae·2024년 7월 17일
post-thumbnail

JFace란?

JFace는 Eclipse 플랫폼의 UI 툴킷 중 하나로, 표준 SWT 위젯을 사용하여 리치한 사용자 인터페이스를 만들 수 있게 해줍니다. 이번 글에서는 ListViewer, TableViewer, TreeViewer 등의 JFace 뷰어를 사용하여 도메인 모델 객체를 UI에 표시하는 방법에 대해 설명하도록 하겠습니다.

레이블 프로바이더 (Label Provider)

레이블 프로바이더는 도메인 모델 객체를 뷰어의 위젯에서 출력할 하나 또는 그 이상의 이미지와 텍스트 문자열에 대응시키는 역할을 합니다.

1. ILabelProvider

주로 리스트와 트리 뷰어에서 사용되며, 각 항목을 단일 이미지와 텍스트 레이블로 변환합니다.

[주요 메서드]

  • getImage(Object element)

    • 특정 요소에 대한 이미지를 반환합니다.
    • 반환된 이미지는 UI에 표시됩니다.
  • getText(Object element)

    • 특정 요소에 대한 텍스트를 반환합니다.
    • 반환된 텍스트는 UI에 표시됩니다.

    예제

    // ILabelProvider 
    import org.eclipse.jface.viewers.ILabelProvider;
    import org.eclipse.jface.viewers.LabelProvider;
    import org.eclipse.swt.graphics.Image;
    
    public class PersonLabelProvider extends LabelProvider {
    
        @Override
        public Image getImage(Object element) {
            // 도메인 모델 객체를 이미지로 변환
            if (element instanceof Person) {
                // Person 객체에 대한 특정 이미지 반환 로직
                return new Image(null, "path/to/image.png");
            }
            return null;
        }
    
        @Override
        public String getText(Object element) {
            // 도메인 모델 객체를 텍스트로 변환
            if (element instanceof Person) {
                Person person = (Person) element;
                return person.getFirstName() + " " + person.getLastName();
            }
            return super.getText(element);
        }
    }

2. ITableLabelProvider

주로 테이블 뷰어에서 사용되며, 각 항목을 여러 개의 이미지와 텍스트 레이블로 변환합니다.

[주요 메서드]

  • getColumnImage(Object element, int columnIndex)

    • 특정 열의 이미지를 반환합니다.
    • 반환된 이미지는 UI의 해당 열에 표시됩니다.
  • getColumnText(Object element, int columnIndex)

    • 특정 열의 텍스트를 반환합니다.
    • 반환된 텍스트는 UI의 해당 열에 표시됩니다.

    예제

    // ITableLabelProvider
    import org.eclipse.jface.viewers.ITableLabelProvider;
    import org.eclipse.jface.viewers.LabelProvider;
    import org.eclipse.swt.graphics.Image;
    
    public class PersonTableLabelProvider extends LabelProvider implements ITableLabelProvider {
    
        @Override
        public Image getColumnImage(Object element, int columnIndex) {
            if (element instanceof Person) {
                Person person = (Person) element;
                switch (columnIndex) {
                    case 0:
                        // 특정 열의 이미지 반환 로직
                        return new Image(null, "path/to/firstNameImage.png");
                    case 1:
                        return new Image(null, "path/to/lastNameImage.png");
                    default:
                        return null;
                }
            }
            return null;
        }
    
        @Override
        public String getColumnText(Object element, int columnIndex) {
            if (element instanceof Person) {
                Person person = (Person) element;
                switch (columnIndex) {
                    case 0:
                        return person.getFirstName();
                    case 1:
                        return person.getLastName();
                    case 2:
                        return String.valueOf(person.getAge());
                    case 3:
                        return String.valueOf(person.getNumChildren());
                    default:
                        return "";
                }
            }
            return null;
        }
    }

컨텐트 프로바이더 (Content Provider)

컨텐트 프로바이더는 도메인 모델 객체를 JFace 뷰어에서 사용할 수 있는 형식으로 변환해주는 역할을 합니다. 이를 통해 복잡한 데이터 구조를 UI에서 쉽게 다룰 수 있습니다.

1. IStructuredContentProvider

IStructuredContentProvider는 리스트나 테이블 뷰어에서 사용되며, 도메인 모델 객체의 컬렉션을 배열로 변환하여 뷰어에 제공합니다.

[주요 메서드]

  • getElements(Object inputElement)

    • 입력된 객체의 요소들을 배열로 반환합니다.
    • 주로 컬렉션 타입의 객체를 배열로 변환하여 반환합니다.
  • inputChanged(Viewer viewer, Object oldInput, Object newInput)

    • 뷰어의 입력이 변경될 때 호출됩니다.
    • 새로운 입력이 설정되기 전에 정리 작업을 수행하거나, 새 입력을 초기화하는 데 사용됩니다.

    예제

    // IStructuredContentProvider 
    import org.eclipse.jface.viewers.IStructuredContentProvider;
    import org.eclipse.jface.viewers.Viewer;
    
    import java.util.List;
    
    public class PersonContentProvider implements IStructuredContentProvider {
    
        @Override
        public Object[] getElements(Object inputElement) {
            if (inputElement instanceof List) {
                return ((List<?>) inputElement).toArray();
            }
            return new Object[0];
        }
    
        @Override
        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
            // 입력이 변경될 때 필요한 작업 수행
        }
    
        @Override
        public void dispose() {
            // 리소스 해제 작업 수행
        }
    }

    위 예제에서는 List 타입의 입력 요소를 배열로 변환하여 반환합니다.

뷰어 정렬자 (Viewer Sorter)

뷰어 정렬자는 컨텐트 프로바이더가 제공하는 요소들을 정렬하는 데 사용됩니다. 정렬자가 없다면 요소들은 컨텐트 프로바이더에서 제공하는 순서대로 출력됩니다.

  • ViewerSorter:
    compare(Viewer, Object, Object): 두 객체를 비교하여 정렬 순서를 결정합니다.

뷰어 필터 (Viewer Filter)

뷰어 필터는 컨텐트 프로바이더에서 제공하는 요소 중 일부만을 출력하는 데 사용됩니다. 필터가 없으면 모든 요소가 출력됩니다.

  • ViewerFilter:
    select(Viewer, Object, Object): 객체가 뷰어에서 보여야 하는지를 지정합니다.

StructuredViewer 클래스

StructuredViewer 클래스는 리스트, 테이블, 트리 뷰어의 추상 상위 클래스로, 하위 클래스에서 공통으로 사용할 만한 유용한 API를 정의합니다.

ListViewer 예제

package com.qualityeclipse.sample;

import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class ListViewerExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("List Viewer Example");
        shell.setBounds(100, 100, 200, 100);
        shell.setLayout(new FillLayout());
        
        final ListViewer listViewer = new ListViewer(shell, SWT.SINGLE);
        listViewer.setLabelProvider(new PersonListLabelProvider());
        listViewer.setContentProvider(new ArrayContentProvider());
        listViewer.setInput(Person.example());
        listViewer.setSorter(new ViewerSorter() {
            public int compare(Viewer viewer, Object p1, Object p2) {
                return ((Person) p1).lastName.compareToIgnoreCase(((Person) p2).lastName);
            }
        });
        
        listViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                System.out.println("Selected: " + selection.getFirstElement());
            }
        });
        
        listViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event.getSelection();
                System.out.println("Double Clicked: " + selection.getFirstElement());
            }
        });
        
        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }
}

코드 분석:

  • ListViewer를 생성하고 셸에 추가합니다.

  • setLabelProvider와 setContentProvider를 사용하여 뷰어에 레이블 및 컨텐트 프로바이더를 설정합니다.

  • setInput을 사용하여 뷰어에 입력 데이터를 제공합니다.

  • setSorter를 사용하여 뷰어의 정렬자를 설정합니다.

  • addSelectionChangedListener와 addDoubleClickListener를 사용하여 선택 변경 및 더블 클릭 이벤트를 처리합니다.

TableViewer 예제

package com.qualityeclipse.sample;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

public class TableViewerExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Table Viewer Example");
        shell.setBounds(100, 100, 325, 200);
        shell.setLayout(new FillLayout());
        
        final TableViewer tableViewer = new TableViewer(shell, SWT.SINGLE | SWT.FULL_SELECTION);
        final Table table = tableViewer.getTable();
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        String[] columnNames = new String[] {"First Name", "Last Name", "Age", "Num Children"};
        int[] columnWidths = new int[] {100, 100, 35, 75};
        int[] columnAlignments = new int[] {SWT.LEFT, SWT.LEFT, SWT.CENTER, SWT.CENTER};
        for (int i = 0; i < columnNames.length; i++) {
            TableColumn tableColumn = new TableColumn(table, columnAlignments[i]);
            tableColumn.setText(columnNames[i]);
            tableColumn.setWidth(columnWidths[i]);
        }

        tableViewer.setLabelProvider(new PersonTableLabelProvider());
        tableViewer.setContentProvider(new ArrayContentProvider());
        tableViewer.setInput(Person.example());

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }
}

코드 분석:

  • TableViewer를 생성하고 셸에 추가합니다.

  • 테이블 컬럼을 생성하고 설정합니다.

  • setLabelProvider와 setContentProvider를 사용하여 뷰어에 레이블 및 컨텐트 프로바이더를 설정합니다.

  • setInput을 사용하여 뷰어에 입력 데이터를 제공합니다.

TreeViewer 예제

package com.qualityeclipse.sample;

import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class TreeViewerExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Tree Viewer Example");
        shell.setBounds(100, 100, 200, 200);
        shell.setLayout(new FillLayout());

        final TreeViewer treeViewer = new TreeViewer(shell, SWT.SINGLE);
        treeViewer.setLabelProvider(new PersonListLabelProvider());
        treeViewer.setContentProvider(new PersonTreeContentProvider());
        treeViewer.setInput(Person.example());

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }
}

코드 분석:

  • TreeViewer를 생성하고 셸에 추가합니다.

  • setLabelProvider와 setContentProvider를 사용하여 뷰어에 레이블 및 컨텐트 프로바이더를 설정합니다.

  • setInput을 사용하여 뷰어에 입력 데이터를 제공합니다.

TextViewer 예제

package com.qualityeclipse.sample;

import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class TextViewerExample {
    public static void main(String[] args) {
        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("Text Viewer Example");
        shell.setBounds(100, 100, 225, 125);
        shell.setLayout(new FillLayout());

        final TextViewer textViewer = new TextViewer(shell, SWT.MULTI | SWT.V_SCROLL);

        String string = "This is plain text\n" + "This is bold text\n" + "This is red text";
        Document document = new Document(string);
        textViewer.setDocument(document);

        TextPresentation style = new TextPresentation();
        style.addStyleRange(new StyleRange(19, 17, null, null, SWT.BOLD));
        Color red = new Color(null, 255, 0, 0);
        style.addStyleRange(new StyleRange(37, 16, red, null));
        textViewer.changeTextPresentation(style, true);

        shell.open();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) display.sleep();
        }
        display.dispose();
    }
}

코드 분석:

  • TextViewer를 생성하고 셸에 추가합니다.

  • 텍스트와 스타일을 설정하여 텍스트를 문서로 나타냅니다.

  • TextPresentation을 사용하여 텍스트 스타일을 적용합니다.

profile
Why not change the code?

0개의 댓글