SlideShare a Scribd company logo
Eclipse



    JFace @ TUES




1            Кирил Митов @ TUES
Същност

      SWT предоставя много възможности за развитие на
       потребителския интерфейс.

      Неудобството се изразява в това, че при представяне на данните
       се използват прости типове като низове, числа, картинки. Това е
       неудобно при работа с обектно ориентиран език като Java.




2                                                 Кирил Митов @ TUES
Проблем

      Трябва да покажете полето name на всеки обект Person




3                                                Кирил Митов @ TUES
Проблем

      Извличате стойността на полето name и я поставяте в списъка




                               name




4                                                Кирил Митов @ TUES
Проблем

      Не може ли някой друг да свърши тази работа!




                               name




5                                                Кирил Митов @ TUES
Решение

       Проблемът може да се реши чрез иползването на JFace

    JFace




6                                                Кирил Митов @ TUES
Същност

      Представянето на обектите се улеснява значително с
       използването на JFace

      JFace представлява библиотека улесняваща извършването на
       често срещани задачи при разработката на потребителски
       интерфейс.

      JFace работи със SWT без да се опитва да го замести.




7                                                  Кирил Митов @ TUES
Същност

      Интересна характеристика на JFace e наличието на така
       наречените „viewers“.

      Viewer-ите са обекти адаптиращи обектно-ориентирания модел
       към потребителския интерфейс. Целта е да се улесни
       изграждането на често срещани графични компоненти като
       структурирани списъци, таблици, дървета.

      Пример за viewer може да бъде видян на фигурата.




8                                                 Кирил Митов @ TUES
Същност

               Всичко, което вижда
                потребителят
                представлява SWT
                компоненти.

               JFace помага за по-
                лесната организация
                на информацията




9                 Кирил Митов @ TUES
Същност

       JFace viewer-ите позволяват директната работа със сложни
        обекти без да се налага на програмиста да представя тези обекти
        като съвкупност от низови и числа. Това се извършва
        автоматично.

       За да се отдели потребителският интерфейс от бизнес логиката на
        приложението се въвеждат няколко допълнителни класа.




10                                                  Кирил Митов @ TUES
Същност

       За да съществува обектът viewer трябва да са зададени
        съответните допълнителни класове
          Задължителни – ContentProvider, LabelProvider
          Незадължителни - ViewerFilter, ViewerComparator

       Пример:
         Даден е масив от цели числа. (inputObject)
         Искаме да изобразим елементите на масива във viewer
          структуриран като списък. За целта ще използваме ListViewer.
          (ContentProvider)
         Трябва да се покажат само четните числа (ViewerFilter)
         Числата трябва да са сортирани в низходящ ред
          (ViewerComparator)
         Числата трябва да са показани в двоичен код (LabelProvider)




11                                                  Кирил Митов @ TUES
Пример




12            Кирил Митов @ TUES
ContentProvider

     Всеки Viewer се нуждае от съдържаниe, което да покаже. Това
     съдържание се извлича от модела. Извличането става с помоща на
     специален обект от тип
     org.eclipse.jface.viewers.IContentProvider
     или неговите най-често използвани наследници
     org.eclipse.jface.viewers.IStucturedContentProvider
     org.eclipse.jface.viewers.ITreeContentProvider


     public interface IStructuredContentProvider extends
     IContentProvider {
         public Object[] getElements(Object inputElement);
     }

     Методът getElements() връща масив от обекти, извлечени от
     входния елемен inputElement.




13                                                 Кирил Митов @ TUES
ContentProvider

     public interface ITreeContentProvider extends
     IStructuredContentProvider {
        public Object[] getChildren(Object parentElement);
        public Object getParent(Object element);
        public boolean hasChildren(Object element);
     }


       getChildren() - резултатът от метода е масив от елементи. Тези
        елементи ще бъдат изобразени като деца на parentElement.
       getParent() - в повечето случаи смислената му имплементация не
        е необходима. Целта е като резултат да се върне родителят на
        посочения елемент.
       hasChildren() - при работа с ITtreeContentProvider първо се вика
        hasChildren() и ако резултатът е true се вика getChildren()




14                                                  Кирил Митов @ TUES
ContentProvider

     Съгласно примера входният елемен е масив с цели числа. Числата
     ще бъдат представени като обекти от тип Integer.
     public class NumbersContentProvider implements
     IStructuredContentProvider {
        public Object[] getElements(Object inputElement) {
            if (inputElement instanceof int[]) {
               int[] array = (int[]) inputElement;
               Integer[] result = new Integer[array.length];
               for (int i = 0; i < array.length; i++) {
                  result[i] = new Integer(array[i]);
               }
               return result;
            }
            return null;
        }};
     Задаването на ContentProvider става по следния начин.
     final StructuredViewer viewer = new TreeViewer(shell,
     SWT.SINGLE);
     viewer.setContentProvider(new NumbersContentProvider());

15                                                Кирил Митов @ TUES
ViewerFilter

     Съдържанието на viewer-а е определено с помощта на
     ContentProvider-а. Следва филтриране на съдържанието.
     Всеки viewer може да има един или няколко филтъра. Филтърът
     представлява обект от тип
     org.eclipse.jface.viewers.ViewerFilter.
     Добавянето на филтър към viewer става с помощта на метода
     StructuredViewer.addFilter().

     public abstract class ViewerFilter {
       /* code missed */

         public abstract boolean select(Viewer viewer, Object
     parentElement,
                 Object element);
     }




16                                               Кирил Митов @ TUES
ViewerFilter

     Основният метод е select(). Методът връща true ако даденият
     елемент минава през филтъра – т.е не се филтрира.
     Логиката на филтрация е отново напълно произволна и зависи само
     от програмиста.
     Съгласно разработвания пример трябва да се показват само
     елементите, които са четни.

     public class NumbersFilter extends ViewerFilter {
        @Override
        public boolean select(Viewer viewer, Object
     parentElement, Object element) {
           if (element instanceof Integer) {
              int value = ((Integer) element).intValue();
              if (value % 2 == 0)
                  return true;
           }
           return false;
        }
     }

17                                               Кирил Митов @ TUES
ViewerFilter

     Добавянето на филтър става по следния начин:

     final StructuredViewer viewer = new ListViewer(shell,
     SWT.SINGLE);
     viewer.addFilter(new NumbersFilter());


     final StructuredViewer viewer = new ListViewer(shell,
     SWT.SINGLE);
     viewer.addFilter(new ViewerFilter(){
         @Override
         public boolean select(Viewer viewer, Object
     parentElement, Object element) {
            if (element instanceof Integer) {
               int value = ((Integer) element).intValue();
               if (value % 2 == 0)
                   return true;
            }
            return false;
         }
18
     });                                       Кирил Митов @ TUES
ViewerComparator

     С помощта на ContentProvider-а е определено съдържанието.
     Следва стъпка на сортиране. Ако използвания viewer го позволява е
     възможно задаването на определен алгоритъм на сортиране на
     елементите. Сортирането се извършва с помощта на обект от тип
     org.eclipse.jface.viewers.ViewerComparator.

     public class ViewerComparator {
        /* . . . */

         public int category(Object element) {
             return 0;
         }

          public int compare(Viewer viewer, Object e1, Object
     e2) {
        /* . . . */
        }
     }


19                                                 Кирил Митов @ TUES
ViewerComparator

     По подразбиране алгоритъмът на сортиране се извършва на две
     стъпки:

       Първо елементите се групират по категории и ранк от 0 до n чрез
        public int category(Object element) {
                return 0;
        }

       След това се извършва сортиране на елементите в категорията
        посредством текстовата презентация на обектите – т.е сортират
        се в азбучен ред.




20                                                  Кирил Митов @ TUES
ViewerComparator

     Съгласно използвания пример числата трябва да са сортирани в
     низходящ ред.
     public class NumbersComparator extends ViewerComparator {
        @Override
        public int compare(Viewer viewer, Object e1, Object e2)
     {
           if ((e1 instanceof Integer)
                 && (e2 instanceof Integer)) {
              return ((Integer) e2).compareTo((Integer) e1);
           }
           throw new IllegalArgumentException("The comparator
     compares only Integers");
        }
     }
     Задаване на обект от тип ViewerComparator
     final StructuredViewer viewer = new ListViewer(shell,
     SWT.SINGLE);
     viewer.setComparator(new NumbersComparator());


21                                             Кирил Митов @ TUES
LabelProvider

     Съдържанието на viewer-а е определено. Елементите са филтрирани
     и сортирани, но все още не са показани на потребителя.
     JFace viewer-ите използват SWT компоненти за представяне на
     информацията. Следователно трябва да се извърши преобразуване
     на елементите от съдържанието към елементи от тип String, Image и
     т.н.
     Това преобразуване се извършва с помощта на обект от тип
     org.eclipse.jface.viewers.ILabelProvider.

     public interface ILabelProvider extends IBaseLabelProvider
     {

         public Image getImage(Object element);

         public String getText(Object element);
     }

     Интерфейсът има два основни метода – getImage() и getText().
     Резултатът върнат от тези методи ще бъде показан на потребителя.

22                                                 Кирил Митов @ TUES
LabelProvider

     Важно!!!. Не всички входни елементи трябва да се поддържат.
     Необходимо е еднотипно решение.

     public String getText(Object element) {
        if (element instanceof java.util.ArrayList) {
             return "java.util.ArrayList";
        } else if (element instanceof java.util.LinkedList) {
             return "java.util.LinkedList";
        }
        thrown new IllegalArgumentException();
        /* A solution is to throw an
          * IllegalArgumentException()
          *
          */
     }




23                                                 Кирил Митов @ TUES
LabelProvider

     Съгласно примера трябва да се показват двоичните кодове на
     съответните числа.
     public class NumbersLabelProvider extends LabelProvider {
        @Override
        public String getText(Object element) {
           if (element instanceof Integer) {
              int value = ((Integer) element).intValue();
              return Integer.toBinaryString(value);
           }
           throw new IllegalArgumentException("This label
     provider supports only Integers");
        }
     }

     Пример за задаване на LabelProvider.
     final StructuredViewer viewer = new TreeViewer(shell,
     SWT.SINGLE);
     viewer.setLabelProvider(new NumberLabelProvider());


24                                            Кирил Митов @ TUES
ListViewer


     int[] input = new int[] { 100, 121, 144, 169, 196 };
     final StructuredViewer viewer = new ListViewer(shell,
     SWT.SINGLE);
     viewer.setContentProvider(new NumbersContentProvider());
     viewer.setLabelProvider(new NumbersLabelProvider());
     viewer.addFilter(new NumbersFilter());
     viewer.setComparator(new NumbersComparator());
     viewer.setInput(input);




25                                            Кирил Митов @ TUES
TableViewer

     TableViewer
       Предоставя изглед на таблица за съответното съдържание.

       Необходими са contentProvider, labelProvider и определен набор
        от колони, в които да се показва информацията.

     Пример:
     Представяне на число в двоичен, десетичен и шестнадесетичен вид.
     Целта е максимално лесно да адаптираме предходния пример към
     новите изисквания.




26                                                  Кирил Митов @ TUES
TableViewer

     За да работи един TableViewer правилно е необходимо да са
     посочени неговите колони и техните имена. Инициализацията се
     извършва по следния начин.

     1 final TableViewer viewer = new TableViewer(shell,
     SWT.SINGLE);
     2 viewer.getTable().setHeaderVisible(true);
     3 viewer.getTable().setLinesVisible(true);
     4 String[] columnNames = new String[] { "Binary", "Dec",
                                                "Hex" };
     5 int[] columnAlignments = new int[] { SWT.LEFT,
                                SWT.CENTER, SWT.RIGHT };
     6 for (int i = 0; i < columnNames.length; i++) {
     7     TableColumn tableColumn = new
     8        TableColumn(viewer.getTable(),
                          columnAlignments[i]);
     9     tableColumn.setText(columnNames[i]);
     10    tableColumn.setWidth(100);
     11 }

27                                                Кирил Митов @ TUES
TableViewer


     2   viewer.getTable().setHeaderVisible(true);
     3   viewer.getTable().setLinesVisible(true);
     4   String[] columnNames = new String[] { "Binary", "Dec",
                                                "Hex" };
     5   int[] columnAlignments = new int[] { SWT.LEFT,
                                 SWT.CENTER, SWT.RIGHT };

     Ред 2: Имената на колоните ще са видими.

     Ред 3: Редовете на таблицата ще са оцветени във сиво през ред.

     Ред 4: Създаване на масив използван за задаване имената на
     колоните.

     Ред 5: Масив определящ подравняването във всяка колона.




28                                                 Кирил Митов @ TUES
TableViewer

     6  for (int i = 0; i < columnNames.length; i++) {
     7     TableColumn tableColumn = new
              TableColumn(viewer.getTable(),
                          columnAlignments[i]);
     8     tableColumn.setText(columnNames[i]);
     9     tableColumn.setWidth(100);
     10 }

     Ред 7: Създаване на нов обект от тип TableColumn. Колоните в
     таблицата представляват деца на таблицата.

     Ред 8: Задаване името на колоната.

     Ред 9: Задаване широчината на колоната.




29                                                  Кирил Митов @ TUES
TableViewer

     В този момент приложението изглежда следния начин:




30                                               Кирил Митов @ TUES
TableViewer

     Съгласно предходния пример – класовете, които няма да
     променяме са
       NumbersContentProvider – съдържанието, което искаме да
        показваме е същото – масив от числа
       NumbersFilter – искаме на филтрираме числата по същият
        признак – т.е по четност
       NumbersComparator – числата отново трябва да са сортирани по
        низходящ ред.

     Тъй като viewer-ът в момента разполага с няколко колони е
     необходимо да се зададе текст за всяка една от клетките.
     Следователно промяната трябва да се извърши в
     NumbersLabelProvider класа.
     NumbersLabelProvider трябва да имплементира интерфейса
     org.eclipse.jface.viewers.ITableLabelProvider




31                                                 Кирил Митов @ TUES
TableViewer

     public class NumbersLabelProvider extends LabelProvider
     implements ITableLabelProvider {
        public String getColumnText(Object element,
                                         int columnIndex) {
           if (!(element instanceof Integer)) {
              throw new IllegalArgumentException("This is a
                            label provider only for Integers");
           }
           int value = ((Integer) element).intValue();
           switch (columnIndex) {
           case 0:return Integer.toBinaryString(value);
           case 1:return Integer.toString(value);
           case 2:return Integer.toHexString(value);
           }
           return null;
        }
     }
     Методът getColumnText() връща резултат спрямо колоната
     определена с columnIndex

32                                             Кирил Митов @ TUES
TableViewer

     Резултатът от реализацията на примера е показа на фигурата.




33                                                 Кирил Митов @ TUES
TreeViewer

       Предоставя възможност за изобразяване на дървовидна
        структура.

       Необходими са contentProvider, labelProvider, входни данни.

     Целта на примера е да модифицираме ListViewer-а, така че като деца
     на всяко число да се показват резултатът от разделянето му на
     десет.
     Класовете които няма да се променят са:
       NumbersLabelProvider
       NumbersComparator
       NumbersFilter

     Промяната се извършва единствено в NumbersContentProvider.
     Тъй като предоставяното съдържание трябва да е в дървовидна
     структура то NumbersContentProvider трябва да имплементира
     org.eclipse.jface.viewers.ITreeContentProvider




34                                                  Кирил Митов @ TUES
TreeViewer

     public class NumbersContentProvider implements
     ITreeContentProvider {

           public Object[] getElements(Object inputElement) {
              return getChildren(inputElement);
           }
           public void dispose() {}
           public void inputChanged(Viewer viewer, Object
                 oldInput, Object newInput) {}
           public Object[] getChildren(Object parentElement) {
              /*explained later*/
           }
           public Object getParent(Object element) {
              return null;
           }
           public boolean hasChildren(Object element) {
              return getChildren(element).length > 0;
           }
     }

35                                            Кирил Митов @ TUES
TreeViewer

     public Object[] getElements(Object inputElement) {
              return getChildren(inputElement);
     }

     public void dispose() {}

     public void inputChanged(Viewer viewer, Object
                   oldInput, Object newInput) {}
     public boolean hasChildren(Object element) {
               return getChildren(element).length > 0;
     }
     Методите dispose() и inputChanged() са с празна имплементация. Тя в
     случая не е необходима.

     Медодът getElements() просто пренасочва своето изпълнение към
     getChildren(). Пренасочването се извършва за пълнота, защото
     ITreeContentProvider е наследник на IStructuredContentProvider, а
     IStructuredContentProvider има метод getElements().


36                                                  Кирил Митов @ TUES
TreeViewer

     1 public Object[] getChildren(Object parentElement) {
     2          if (parentElement instanceof int[]) {
     4             int[] array = (int[]) parentElement;
     5             Integer[] result = new Integer[array.length];
     6             for (int i = 0; i < array.length; i++) {
     7                 result[i] = new Integer(array[i]);
     8             }
     9             return result;
     10         } else if (parentElement instanceof Integer) {
     11            int value = ((Integer)
     12                               parentElement).intValue();
     13            if (value > 10) return new Integer[] {
                       new Integer( value / 10) };
     14         }
     15         return new Object[0];//must not return null or
     }                    //hasChildren() will fail
     Ред 10-14: Ако обектът е от тип Integer то се връща масив от един
     елемент. Този елемент е отново обект от тип Integer, но стойността е
     вече разделена на десет.

37                                                   Кирил Митов @ TUES
TreeViewer

     Резултатът от изпълнението на програмата е показан на фиг.1.
     За улеснение на фиг.2 е показан същият резултат, но с десетични
     числа.




               Фиг.1                            Фиг.2


38                                                  Кирил Митов @ TUES
TableViewer - Редактиране

     Редактиране на таблица
     Задачата на този пример е да се изгради TableViewer, който да
     позволява редактиране на елементите показвани в неговите клетки.
     Възможно е въвеждането само на цели числа. Позволява се
     редакция само на средната колона – т.е на тази с десетичните числа.

     За целта ще се използва досега разработения TableViewer. С цел
     премахване на излишната сложност следните класове няма да
     бъдат използвани:

         NumbersComparator

         NumbersFilter




39                                                  Кирил Митов @ TUES
TableViewer - Редактиране

     Крайният резултат от редактирането ще изглежда по следният начин




40                                                Кирил Митов @ TUES
TableViewer - Редактиране

     Капсулираме необходимите обекти в нов клас - TableEditor

     1   public class TableEditor {

     2      private TableViewer fTableViewer;
     3      private int[] fInput = new int[] { 100, 121, 144,
                                                169,196, 1024 };
     4      private static String[] COLUMN_NAMES = new String[]
                        { "Binary", "Dec", "Hex" };;
     5      public static void main(String[] args) {
     6         TableEditor editor = new TableEditor();
     7         editor.createComposite();
     8      }
         /* ... code missed ...*/
     }
     Ред 2: Обектът от тип TableViewer.

     Ред 3: Входните данни за viewer-а.

     Ред 4: Имената на колоните на таблицата
41                                                 Кирил Митов @ TUES
TableViewer - Редактиране

     Методът TableEditor.createComposite() изглежда по следният начин:
        public void createComposite() {
        /*... code missed - creating shell */
           Group group = new Group(shell, SWT.NONE);
           group.setText("TableEditor example");
           group.setLayout(new GridLayout(1, false));
           group.setLayoutData(new
                                 GridData(GridData.FILL_BOTH));
           fTableViewer = createTableViewer(group);
           addColumns(fTableViewer);
           createViewerEditors();
           fTableViewer.setInput(fInput);
        /*...code missed – opening shell */
        }

     Основната идея на този метод е да инициализира fTableViewer,
     добави колоните и създаде обектите необходиме за редактиране
     съдържанието на таблицата. Ще бъда разгледани всичките методи.


42                                                  Кирил Митов @ TUES
TableViewer - Редактиране

     1 protected TableViewer createTableViewer(Composite
     2 parent) {
     3 TableViewer viewer = new TableViewer(parent, SWT.BORDER
                                               | SWT.SINGLE);
     5 viewer.setContentProvider(new
                                NumbersContentProvider());
     6 viewer.setLabelProvider(new
                                NumbersTableLabelProvider());
     7 GridData data = new GridData();
     8 data.horizontalAlignment = GridData.FILL;
     9 data.verticalAlignment = GridData.FILL;
     10 data.grabExcessHorizontalSpace = true;
     11 data.grabExcessVerticalSpace = true;
     12 viewer.getTable().setLayoutData(data);
     13 return viewer;
     14}

     Ред 7,8,9,10,11,12: viewer-ът ще бъде разположен, така че да заема
     цялото му отделено пространство.
43                                                    Кирил Митов @ TUES
TableViewer - Редактиране

     protected void addColumns(TableViewer viewer) {
           viewer.getTable().setHeaderVisible(true);
           viewer.getTable().setLinesVisible(true);
           for (int i = 0; i < COLUMN_NAMES.length; i++) {
              TableColumn tableColumn = new
                 TableColumn(viewer.getTable(), SWT.RIGHT);
              tableColumn.setText(COLUMN_NAMES[i]);
              tableColumn.setWidth(100);
           }
     }

     След създаването на таблицата е необходимо да се създадат и
     колоните й.

     Всяка колона има ИМЕ, ПОДРАВНЯВАНЕ, ШИРИНА.

     При създаването си всяка колона приема таблицата като параметър
     на конструктура си.


44                                                Кирил Митов @ TUES
TableViewer - Редактиране

     Възможността за редактиране изисква използването на следните
     допълнителни обекти:

       org.eclipse.jface.viewers.TextCellEditor – отговаря за
        визуалните аспекти относно редактирането и координира
        работата на останалите обекти свързани с редакцията.

       org.eclipse.jface.viewers.ICellEditorValidator –
        позволява валидация на въведената стойност. Разглежданият
        пример има за цел да позволява въвеждането само на
        целочислени числа.

       org.eclipse.jface.viewers.ICellModifier – служи като
        посредник между входните данни и данните показвани в
        графичната част. Има за цел да обработи входната информация
        преди и след редактирането и в графичната част.




45                                                Кирил Митов @ TUES
TableViewer - Редактиране

     TextCellEditor
     1   TextCellEditor editor = new
                  TextCellEditor(fTableViewer.getTable());
     2   fTableViewer.setCellEditors(
                  new CellEditor[] { null,editor, null });

     Ред 1: Създава се нов обект от тип TextCellEditor.

     Ред 2: В разработвания пример таблицата има три колони.
     Следователно на всеки ред има по три клетки. За всяка клетка може
     да се използва отделен редактор. Това се налага поради факта, че
     отделните колони/клетки показват различна по тип информация. В
     една клетка може да се въвеждат низове докато в друга да се
     избират цветове. В случай целта е да се редактира само средната
     колона – за другите две не се задават редактори

            new CellEditor[] { null,editor, null })


46                                                    Кирил Митов @ TUES
TableViewer - Редактиране

     ICellEditorValidator
     1 editor.setValidator(new ICellEditorValidator() {
     2       public String isValid(Object value) {
     3          if (value instanceof String) {
     4             try {
     5                Integer.parseInt((String) value);
     6                return null;
     7             } catch (NumberFormatException e) {
     8                return "Only numbers allowed";
     9             }
     10         }
     11         return "Unsupported value";
     12      }});

     Ред 2: ICellEditorValidator има един метод – isValid() приемащ като
     параметър въведената от потребителя стойност. Методът трябва да
     върне null ако стойността е валидна.
     Ред 5: Стойността ще е валидна само ако е текстов низ, който може
     да се преобразува в цяло число

47                                                   Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier
     Най-сложният обект в дадения пример. Служи като контролер между
     потребителския интерфейс и входните данни
     fTableViewer.setCellModifier(new ICellModifier() {
              public boolean canModify(Object element, String
     property) { /* ...code missed ...*/ }
              public Object getValue(Object element, String
     property) { /* ...code missed ...*/ }
              public void modify(Object element, String
     property, Object value) { /* ...code missed ...*/ }
              }
     });
     И трите метода приемат параметър String property. Целта му е да
     определи коя колона се редактира. Възможно е да съществуват
     различни редактори за различните колони, но съществува единствен
     обект от тип IСellModifier.



48                                                Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier

     Всяка колона има характеристика отговаряща на параметъра
     property. При редактирането на дадена колона като параметър се
     предава тази стойност.

     Задаването на property става чрез

     fTableViewer.setColumnProperties(COLUMN_NAMES);

     В случай COLUMN_NAMES е масив от низове. Представлява имената
     на колоните. По този начин имената ще се използват за различаване
     на различните колони при тяхното редактиране.




49                                                 Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier - canModify(...)

     1   fTableViewer.setCellModifier(new ICellModifier() {
     2         public boolean canModify(Object element, String
     3   property) {
     4            if (COLUMN_NAMES[1].equals(property) {
     5               return true;
     6            }
     7            return false;
     8         }
            /* ...code missed...*/
     }

     Методът определя коя колона може да се редактира и коя не. В
     случай ред 4 проверява дали потребителят се опитва да редактира
     колоната с характеристика COLUMN_NAMES[1] - “Dec”.




50                                                Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier - getValue(...)
     1   fTableViewer.setCellModifier(new ICellModifier() {
     2         public Object getValue(Object element, String
     3   property) {
     4            if (COLUMN_NAMES[1].equals(property)) {
     5               return ((Integer) element).toString();
     6            }
     7            return null;
     8         }
         /* ...code missed ...*/
     }

     Методът определя стойността на дадената колона. В дадения пример
     задължително трябва да върен низ. Ред 5 извършва
     преобразуването от обект Integer към String.




51                                                Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier - modify(...)
     1 fTableViewer.setCellModifier(new ICellModifier() {
     2     public void modify(Object element, String property,
     Object value) {
     3        if (element instanceof TableItem
                 && value != null) {
     4        int index = ((TableItem) element).
                          getParent().
                          indexOf((TableItem) element);
     5        if (COLUMN_NAMES[1].equals(property)) {
     6        fInput[index] =
                       Integer.parseInt((String) value);
     7        }
     8        fTableViewer.refresh();
           }}
     });




52                                            Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier - modify(...)

     3         if (element instanceof TableItem
                  && value != null) {
     4         int index = ((TableItem) element).
                           getParent().
                           indexOf((TableItem) element);

     Ред 3: Проверка за коректност на предадените данни. Предаденият
     за редакция елемент трябва да е от тип TableItem. Новата стойност
     value не трябва да е null. (Възможно е да е null ако се извърши
     невалидно въвеждане.)
     Ред4: TableItem представлява ред от таблицата. В ред 4 намираме
     индекса на този ред. Този индекс ни е необходим, за да промениме
     стойността във входния масив. Посочения тук подход се отнася само
     за разработвания пример. Възможни са други решения.



53                                                  Кирил Митов @ TUES
TableViewer - Редактиране

     ICellModifier - modify(...)
     5          if (COLUMN_NAMES[1].equals(property)) {
     6          fInput[index] =
                         Integer.parseInt((String) value);
     7          }
     8          fTableViewer.refresh();
           }}

     Ред 5: Проверка за колоната.

     Ред 6: Нововъведената от потребителя стойност се предава чрез
     параметъра value. Тъй като вече е намерен индексът на
     редактирания елемент се променя стойността във входния масив.

     Ред 8: Входните данни са променени. Следователно таблицата
     трябва да се обнови. Обновяването се извършва чрез метода
     fTableViewer.refresh()



54                                                Кирил Митов @ TUES
TableViewer - Редактиране

     Разработеният viewer дава възможност за редакция и валидация на
     редактираните стойностти. След промяната на някое число
     таблицата се обновява и новите стойности се изписват.




55                                                Кирил Митов @ TUES
Обобщение

       JFace предоставя viewer-и. Тези viewer-и се зползват като обвивка
        на обектите и улесняват значително тяхното графично
        изобразяване.

       JFace не предоставя само viewer-и. Налични са още магьосници
        (wizards), диалогови прозорци (dialogs), класове улесняващи
        текстообработката и др.

       JFace не е графична библиотека и няма за цел да замени SWT, а
        да предостави допълнителни улеснения на програмиста при
        използването на SWT. Възможна е реализацията на графично
        приложение и без JFace.




56                                                  Кирил Митов @ TUES
Copyright

       This work is licensed under the Creative Commons
       Attribution-Noncommercial-Share   Alike  2.5  Bulgaria
       License. To view a copy of this license, visit http://
       creativecommons.org/licenses/by-nc-sa/2.5/bg/ or send
       a letter to Creative Commons, 171 Second Street, Suite
       300, San Francisco, California, 94105, USA.




57                                           Кирил Митов @ TUES

More Related Content

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
Marius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
Expeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
Pixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
ThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
marketingartwork
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
Skeleton Technologies
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
Kurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
SpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Lily Ray
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
Rajiv Jayarajah, MAppComm, ACC
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
Christy Abraham Joy
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
Vit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
MindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

JFace@TUES

  • 1. Eclipse JFace @ TUES 1 Кирил Митов @ TUES
  • 2. Същност  SWT предоставя много възможности за развитие на потребителския интерфейс.  Неудобството се изразява в това, че при представяне на данните се използват прости типове като низове, числа, картинки. Това е неудобно при работа с обектно ориентиран език като Java. 2 Кирил Митов @ TUES
  • 3. Проблем Трябва да покажете полето name на всеки обект Person 3 Кирил Митов @ TUES
  • 4. Проблем Извличате стойността на полето name и я поставяте в списъка name 4 Кирил Митов @ TUES
  • 5. Проблем Не може ли някой друг да свърши тази работа! name 5 Кирил Митов @ TUES
  • 6. Решение Проблемът може да се реши чрез иползването на JFace JFace 6 Кирил Митов @ TUES
  • 7. Същност  Представянето на обектите се улеснява значително с използването на JFace  JFace представлява библиотека улесняваща извършването на често срещани задачи при разработката на потребителски интерфейс.  JFace работи със SWT без да се опитва да го замести. 7 Кирил Митов @ TUES
  • 8. Същност  Интересна характеристика на JFace e наличието на така наречените „viewers“.  Viewer-ите са обекти адаптиращи обектно-ориентирания модел към потребителския интерфейс. Целта е да се улесни изграждането на често срещани графични компоненти като структурирани списъци, таблици, дървета.  Пример за viewer може да бъде видян на фигурата. 8 Кирил Митов @ TUES
  • 9. Същност  Всичко, което вижда потребителят представлява SWT компоненти.  JFace помага за по- лесната организация на информацията 9 Кирил Митов @ TUES
  • 10. Същност  JFace viewer-ите позволяват директната работа със сложни обекти без да се налага на програмиста да представя тези обекти като съвкупност от низови и числа. Това се извършва автоматично.  За да се отдели потребителският интерфейс от бизнес логиката на приложението се въвеждат няколко допълнителни класа. 10 Кирил Митов @ TUES
  • 11. Същност  За да съществува обектът viewer трябва да са зададени съответните допълнителни класове  Задължителни – ContentProvider, LabelProvider  Незадължителни - ViewerFilter, ViewerComparator  Пример:  Даден е масив от цели числа. (inputObject)  Искаме да изобразим елементите на масива във viewer структуриран като списък. За целта ще използваме ListViewer. (ContentProvider)  Трябва да се покажат само четните числа (ViewerFilter)  Числата трябва да са сортирани в низходящ ред (ViewerComparator)  Числата трябва да са показани в двоичен код (LabelProvider) 11 Кирил Митов @ TUES
  • 12. Пример 12 Кирил Митов @ TUES
  • 13. ContentProvider Всеки Viewer се нуждае от съдържаниe, което да покаже. Това съдържание се извлича от модела. Извличането става с помоща на специален обект от тип org.eclipse.jface.viewers.IContentProvider или неговите най-често използвани наследници org.eclipse.jface.viewers.IStucturedContentProvider org.eclipse.jface.viewers.ITreeContentProvider public interface IStructuredContentProvider extends IContentProvider { public Object[] getElements(Object inputElement); } Методът getElements() връща масив от обекти, извлечени от входния елемен inputElement. 13 Кирил Митов @ TUES
  • 14. ContentProvider public interface ITreeContentProvider extends IStructuredContentProvider { public Object[] getChildren(Object parentElement); public Object getParent(Object element); public boolean hasChildren(Object element); }  getChildren() - резултатът от метода е масив от елементи. Тези елементи ще бъдат изобразени като деца на parentElement.  getParent() - в повечето случаи смислената му имплементация не е необходима. Целта е като резултат да се върне родителят на посочения елемент.  hasChildren() - при работа с ITtreeContentProvider първо се вика hasChildren() и ако резултатът е true се вика getChildren() 14 Кирил Митов @ TUES
  • 15. ContentProvider Съгласно примера входният елемен е масив с цели числа. Числата ще бъдат представени като обекти от тип Integer. public class NumbersContentProvider implements IStructuredContentProvider { public Object[] getElements(Object inputElement) { if (inputElement instanceof int[]) { int[] array = (int[]) inputElement; Integer[] result = new Integer[array.length]; for (int i = 0; i < array.length; i++) { result[i] = new Integer(array[i]); } return result; } return null; }}; Задаването на ContentProvider става по следния начин. final StructuredViewer viewer = new TreeViewer(shell, SWT.SINGLE); viewer.setContentProvider(new NumbersContentProvider()); 15 Кирил Митов @ TUES
  • 16. ViewerFilter Съдържанието на viewer-а е определено с помощта на ContentProvider-а. Следва филтриране на съдържанието. Всеки viewer може да има един или няколко филтъра. Филтърът представлява обект от тип org.eclipse.jface.viewers.ViewerFilter. Добавянето на филтър към viewer става с помощта на метода StructuredViewer.addFilter(). public abstract class ViewerFilter { /* code missed */ public abstract boolean select(Viewer viewer, Object parentElement, Object element); } 16 Кирил Митов @ TUES
  • 17. ViewerFilter Основният метод е select(). Методът връща true ако даденият елемент минава през филтъра – т.е не се филтрира. Логиката на филтрация е отново напълно произволна и зависи само от програмиста. Съгласно разработвания пример трябва да се показват само елементите, които са четни. public class NumbersFilter extends ViewerFilter { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof Integer) { int value = ((Integer) element).intValue(); if (value % 2 == 0) return true; } return false; } } 17 Кирил Митов @ TUES
  • 18. ViewerFilter Добавянето на филтър става по следния начин: final StructuredViewer viewer = new ListViewer(shell, SWT.SINGLE); viewer.addFilter(new NumbersFilter()); final StructuredViewer viewer = new ListViewer(shell, SWT.SINGLE); viewer.addFilter(new ViewerFilter(){ @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof Integer) { int value = ((Integer) element).intValue(); if (value % 2 == 0) return true; } return false; } 18 }); Кирил Митов @ TUES
  • 19. ViewerComparator С помощта на ContentProvider-а е определено съдържанието. Следва стъпка на сортиране. Ако използвания viewer го позволява е възможно задаването на определен алгоритъм на сортиране на елементите. Сортирането се извършва с помощта на обект от тип org.eclipse.jface.viewers.ViewerComparator. public class ViewerComparator { /* . . . */ public int category(Object element) { return 0; } public int compare(Viewer viewer, Object e1, Object e2) { /* . . . */ } } 19 Кирил Митов @ TUES
  • 20. ViewerComparator По подразбиране алгоритъмът на сортиране се извършва на две стъпки:  Първо елементите се групират по категории и ранк от 0 до n чрез public int category(Object element) { return 0; }  След това се извършва сортиране на елементите в категорията посредством текстовата презентация на обектите – т.е сортират се в азбучен ред. 20 Кирил Митов @ TUES
  • 21. ViewerComparator Съгласно използвания пример числата трябва да са сортирани в низходящ ред. public class NumbersComparator extends ViewerComparator { @Override public int compare(Viewer viewer, Object e1, Object e2) { if ((e1 instanceof Integer) && (e2 instanceof Integer)) { return ((Integer) e2).compareTo((Integer) e1); } throw new IllegalArgumentException("The comparator compares only Integers"); } } Задаване на обект от тип ViewerComparator final StructuredViewer viewer = new ListViewer(shell, SWT.SINGLE); viewer.setComparator(new NumbersComparator()); 21 Кирил Митов @ TUES
  • 22. LabelProvider Съдържанието на viewer-а е определено. Елементите са филтрирани и сортирани, но все още не са показани на потребителя. JFace viewer-ите използват SWT компоненти за представяне на информацията. Следователно трябва да се извърши преобразуване на елементите от съдържанието към елементи от тип String, Image и т.н. Това преобразуване се извършва с помощта на обект от тип org.eclipse.jface.viewers.ILabelProvider. public interface ILabelProvider extends IBaseLabelProvider { public Image getImage(Object element); public String getText(Object element); } Интерфейсът има два основни метода – getImage() и getText(). Резултатът върнат от тези методи ще бъде показан на потребителя. 22 Кирил Митов @ TUES
  • 23. LabelProvider Важно!!!. Не всички входни елементи трябва да се поддържат. Необходимо е еднотипно решение. public String getText(Object element) { if (element instanceof java.util.ArrayList) { return "java.util.ArrayList"; } else if (element instanceof java.util.LinkedList) { return "java.util.LinkedList"; } thrown new IllegalArgumentException(); /* A solution is to throw an * IllegalArgumentException() * */ } 23 Кирил Митов @ TUES
  • 24. LabelProvider Съгласно примера трябва да се показват двоичните кодове на съответните числа. public class NumbersLabelProvider extends LabelProvider { @Override public String getText(Object element) { if (element instanceof Integer) { int value = ((Integer) element).intValue(); return Integer.toBinaryString(value); } throw new IllegalArgumentException("This label provider supports only Integers"); } } Пример за задаване на LabelProvider. final StructuredViewer viewer = new TreeViewer(shell, SWT.SINGLE); viewer.setLabelProvider(new NumberLabelProvider()); 24 Кирил Митов @ TUES
  • 25. ListViewer int[] input = new int[] { 100, 121, 144, 169, 196 }; final StructuredViewer viewer = new ListViewer(shell, SWT.SINGLE); viewer.setContentProvider(new NumbersContentProvider()); viewer.setLabelProvider(new NumbersLabelProvider()); viewer.addFilter(new NumbersFilter()); viewer.setComparator(new NumbersComparator()); viewer.setInput(input); 25 Кирил Митов @ TUES
  • 26. TableViewer TableViewer  Предоставя изглед на таблица за съответното съдържание.  Необходими са contentProvider, labelProvider и определен набор от колони, в които да се показва информацията. Пример: Представяне на число в двоичен, десетичен и шестнадесетичен вид. Целта е максимално лесно да адаптираме предходния пример към новите изисквания. 26 Кирил Митов @ TUES
  • 27. TableViewer За да работи един TableViewer правилно е необходимо да са посочени неговите колони и техните имена. Инициализацията се извършва по следния начин. 1 final TableViewer viewer = new TableViewer(shell, SWT.SINGLE); 2 viewer.getTable().setHeaderVisible(true); 3 viewer.getTable().setLinesVisible(true); 4 String[] columnNames = new String[] { "Binary", "Dec", "Hex" }; 5 int[] columnAlignments = new int[] { SWT.LEFT, SWT.CENTER, SWT.RIGHT }; 6 for (int i = 0; i < columnNames.length; i++) { 7 TableColumn tableColumn = new 8 TableColumn(viewer.getTable(), columnAlignments[i]); 9 tableColumn.setText(columnNames[i]); 10 tableColumn.setWidth(100); 11 } 27 Кирил Митов @ TUES
  • 28. TableViewer 2 viewer.getTable().setHeaderVisible(true); 3 viewer.getTable().setLinesVisible(true); 4 String[] columnNames = new String[] { "Binary", "Dec", "Hex" }; 5 int[] columnAlignments = new int[] { SWT.LEFT, SWT.CENTER, SWT.RIGHT }; Ред 2: Имената на колоните ще са видими. Ред 3: Редовете на таблицата ще са оцветени във сиво през ред. Ред 4: Създаване на масив използван за задаване имената на колоните. Ред 5: Масив определящ подравняването във всяка колона. 28 Кирил Митов @ TUES
  • 29. TableViewer 6 for (int i = 0; i < columnNames.length; i++) { 7 TableColumn tableColumn = new TableColumn(viewer.getTable(), columnAlignments[i]); 8 tableColumn.setText(columnNames[i]); 9 tableColumn.setWidth(100); 10 } Ред 7: Създаване на нов обект от тип TableColumn. Колоните в таблицата представляват деца на таблицата. Ред 8: Задаване името на колоната. Ред 9: Задаване широчината на колоната. 29 Кирил Митов @ TUES
  • 30. TableViewer В този момент приложението изглежда следния начин: 30 Кирил Митов @ TUES
  • 31. TableViewer Съгласно предходния пример – класовете, които няма да променяме са  NumbersContentProvider – съдържанието, което искаме да показваме е същото – масив от числа  NumbersFilter – искаме на филтрираме числата по същият признак – т.е по четност  NumbersComparator – числата отново трябва да са сортирани по низходящ ред. Тъй като viewer-ът в момента разполага с няколко колони е необходимо да се зададе текст за всяка една от клетките. Следователно промяната трябва да се извърши в NumbersLabelProvider класа. NumbersLabelProvider трябва да имплементира интерфейса org.eclipse.jface.viewers.ITableLabelProvider 31 Кирил Митов @ TUES
  • 32. TableViewer public class NumbersLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object element, int columnIndex) { if (!(element instanceof Integer)) { throw new IllegalArgumentException("This is a label provider only for Integers"); } int value = ((Integer) element).intValue(); switch (columnIndex) { case 0:return Integer.toBinaryString(value); case 1:return Integer.toString(value); case 2:return Integer.toHexString(value); } return null; } } Методът getColumnText() връща резултат спрямо колоната определена с columnIndex 32 Кирил Митов @ TUES
  • 33. TableViewer Резултатът от реализацията на примера е показа на фигурата. 33 Кирил Митов @ TUES
  • 34. TreeViewer  Предоставя възможност за изобразяване на дървовидна структура.  Необходими са contentProvider, labelProvider, входни данни. Целта на примера е да модифицираме ListViewer-а, така че като деца на всяко число да се показват резултатът от разделянето му на десет. Класовете които няма да се променят са:  NumbersLabelProvider  NumbersComparator  NumbersFilter Промяната се извършва единствено в NumbersContentProvider. Тъй като предоставяното съдържание трябва да е в дървовидна структура то NumbersContentProvider трябва да имплементира org.eclipse.jface.viewers.ITreeContentProvider 34 Кирил Митов @ TUES
  • 35. TreeViewer public class NumbersContentProvider implements ITreeContentProvider { public Object[] getElements(Object inputElement) { return getChildren(inputElement); } public void dispose() {} public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} public Object[] getChildren(Object parentElement) { /*explained later*/ } public Object getParent(Object element) { return null; } public boolean hasChildren(Object element) { return getChildren(element).length > 0; } } 35 Кирил Митов @ TUES
  • 36. TreeViewer public Object[] getElements(Object inputElement) { return getChildren(inputElement); } public void dispose() {} public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {} public boolean hasChildren(Object element) { return getChildren(element).length > 0; } Методите dispose() и inputChanged() са с празна имплементация. Тя в случая не е необходима. Медодът getElements() просто пренасочва своето изпълнение към getChildren(). Пренасочването се извършва за пълнота, защото ITreeContentProvider е наследник на IStructuredContentProvider, а IStructuredContentProvider има метод getElements(). 36 Кирил Митов @ TUES
  • 37. TreeViewer 1 public Object[] getChildren(Object parentElement) { 2 if (parentElement instanceof int[]) { 4 int[] array = (int[]) parentElement; 5 Integer[] result = new Integer[array.length]; 6 for (int i = 0; i < array.length; i++) { 7 result[i] = new Integer(array[i]); 8 } 9 return result; 10 } else if (parentElement instanceof Integer) { 11 int value = ((Integer) 12 parentElement).intValue(); 13 if (value > 10) return new Integer[] { new Integer( value / 10) }; 14 } 15 return new Object[0];//must not return null or } //hasChildren() will fail Ред 10-14: Ако обектът е от тип Integer то се връща масив от един елемент. Този елемент е отново обект от тип Integer, но стойността е вече разделена на десет. 37 Кирил Митов @ TUES
  • 38. TreeViewer Резултатът от изпълнението на програмата е показан на фиг.1. За улеснение на фиг.2 е показан същият резултат, но с десетични числа. Фиг.1 Фиг.2 38 Кирил Митов @ TUES
  • 39. TableViewer - Редактиране Редактиране на таблица Задачата на този пример е да се изгради TableViewer, който да позволява редактиране на елементите показвани в неговите клетки. Възможно е въвеждането само на цели числа. Позволява се редакция само на средната колона – т.е на тази с десетичните числа. За целта ще се използва досега разработения TableViewer. С цел премахване на излишната сложност следните класове няма да бъдат използвани:  NumbersComparator  NumbersFilter 39 Кирил Митов @ TUES
  • 40. TableViewer - Редактиране Крайният резултат от редактирането ще изглежда по следният начин 40 Кирил Митов @ TUES
  • 41. TableViewer - Редактиране Капсулираме необходимите обекти в нов клас - TableEditor 1 public class TableEditor { 2 private TableViewer fTableViewer; 3 private int[] fInput = new int[] { 100, 121, 144, 169,196, 1024 }; 4 private static String[] COLUMN_NAMES = new String[] { "Binary", "Dec", "Hex" };; 5 public static void main(String[] args) { 6 TableEditor editor = new TableEditor(); 7 editor.createComposite(); 8 } /* ... code missed ...*/ } Ред 2: Обектът от тип TableViewer. Ред 3: Входните данни за viewer-а. Ред 4: Имената на колоните на таблицата 41 Кирил Митов @ TUES
  • 42. TableViewer - Редактиране Методът TableEditor.createComposite() изглежда по следният начин: public void createComposite() { /*... code missed - creating shell */ Group group = new Group(shell, SWT.NONE); group.setText("TableEditor example"); group.setLayout(new GridLayout(1, false)); group.setLayoutData(new GridData(GridData.FILL_BOTH)); fTableViewer = createTableViewer(group); addColumns(fTableViewer); createViewerEditors(); fTableViewer.setInput(fInput); /*...code missed – opening shell */ } Основната идея на този метод е да инициализира fTableViewer, добави колоните и създаде обектите необходиме за редактиране съдържанието на таблицата. Ще бъда разгледани всичките методи. 42 Кирил Митов @ TUES
  • 43. TableViewer - Редактиране 1 protected TableViewer createTableViewer(Composite 2 parent) { 3 TableViewer viewer = new TableViewer(parent, SWT.BORDER | SWT.SINGLE); 5 viewer.setContentProvider(new NumbersContentProvider()); 6 viewer.setLabelProvider(new NumbersTableLabelProvider()); 7 GridData data = new GridData(); 8 data.horizontalAlignment = GridData.FILL; 9 data.verticalAlignment = GridData.FILL; 10 data.grabExcessHorizontalSpace = true; 11 data.grabExcessVerticalSpace = true; 12 viewer.getTable().setLayoutData(data); 13 return viewer; 14} Ред 7,8,9,10,11,12: viewer-ът ще бъде разположен, така че да заема цялото му отделено пространство. 43 Кирил Митов @ TUES
  • 44. TableViewer - Редактиране protected void addColumns(TableViewer viewer) { viewer.getTable().setHeaderVisible(true); viewer.getTable().setLinesVisible(true); for (int i = 0; i < COLUMN_NAMES.length; i++) { TableColumn tableColumn = new TableColumn(viewer.getTable(), SWT.RIGHT); tableColumn.setText(COLUMN_NAMES[i]); tableColumn.setWidth(100); } } След създаването на таблицата е необходимо да се създадат и колоните й. Всяка колона има ИМЕ, ПОДРАВНЯВАНЕ, ШИРИНА. При създаването си всяка колона приема таблицата като параметър на конструктура си. 44 Кирил Митов @ TUES
  • 45. TableViewer - Редактиране Възможността за редактиране изисква използването на следните допълнителни обекти:  org.eclipse.jface.viewers.TextCellEditor – отговаря за визуалните аспекти относно редактирането и координира работата на останалите обекти свързани с редакцията.  org.eclipse.jface.viewers.ICellEditorValidator – позволява валидация на въведената стойност. Разглежданият пример има за цел да позволява въвеждането само на целочислени числа.  org.eclipse.jface.viewers.ICellModifier – служи като посредник между входните данни и данните показвани в графичната част. Има за цел да обработи входната информация преди и след редактирането и в графичната част. 45 Кирил Митов @ TUES
  • 46. TableViewer - Редактиране TextCellEditor 1 TextCellEditor editor = new TextCellEditor(fTableViewer.getTable()); 2 fTableViewer.setCellEditors( new CellEditor[] { null,editor, null }); Ред 1: Създава се нов обект от тип TextCellEditor. Ред 2: В разработвания пример таблицата има три колони. Следователно на всеки ред има по три клетки. За всяка клетка може да се използва отделен редактор. Това се налага поради факта, че отделните колони/клетки показват различна по тип информация. В една клетка може да се въвеждат низове докато в друга да се избират цветове. В случай целта е да се редактира само средната колона – за другите две не се задават редактори new CellEditor[] { null,editor, null }) 46 Кирил Митов @ TUES
  • 47. TableViewer - Редактиране ICellEditorValidator 1 editor.setValidator(new ICellEditorValidator() { 2 public String isValid(Object value) { 3 if (value instanceof String) { 4 try { 5 Integer.parseInt((String) value); 6 return null; 7 } catch (NumberFormatException e) { 8 return "Only numbers allowed"; 9 } 10 } 11 return "Unsupported value"; 12 }}); Ред 2: ICellEditorValidator има един метод – isValid() приемащ като параметър въведената от потребителя стойност. Методът трябва да върне null ако стойността е валидна. Ред 5: Стойността ще е валидна само ако е текстов низ, който може да се преобразува в цяло число 47 Кирил Митов @ TUES
  • 48. TableViewer - Редактиране ICellModifier Най-сложният обект в дадения пример. Служи като контролер между потребителския интерфейс и входните данни fTableViewer.setCellModifier(new ICellModifier() { public boolean canModify(Object element, String property) { /* ...code missed ...*/ } public Object getValue(Object element, String property) { /* ...code missed ...*/ } public void modify(Object element, String property, Object value) { /* ...code missed ...*/ } } }); И трите метода приемат параметър String property. Целта му е да определи коя колона се редактира. Възможно е да съществуват различни редактори за различните колони, но съществува единствен обект от тип IСellModifier. 48 Кирил Митов @ TUES
  • 49. TableViewer - Редактиране ICellModifier Всяка колона има характеристика отговаряща на параметъра property. При редактирането на дадена колона като параметър се предава тази стойност. Задаването на property става чрез fTableViewer.setColumnProperties(COLUMN_NAMES); В случай COLUMN_NAMES е масив от низове. Представлява имената на колоните. По този начин имената ще се използват за различаване на различните колони при тяхното редактиране. 49 Кирил Митов @ TUES
  • 50. TableViewer - Редактиране ICellModifier - canModify(...) 1 fTableViewer.setCellModifier(new ICellModifier() { 2 public boolean canModify(Object element, String 3 property) { 4 if (COLUMN_NAMES[1].equals(property) { 5 return true; 6 } 7 return false; 8 } /* ...code missed...*/ } Методът определя коя колона може да се редактира и коя не. В случай ред 4 проверява дали потребителят се опитва да редактира колоната с характеристика COLUMN_NAMES[1] - “Dec”. 50 Кирил Митов @ TUES
  • 51. TableViewer - Редактиране ICellModifier - getValue(...) 1 fTableViewer.setCellModifier(new ICellModifier() { 2 public Object getValue(Object element, String 3 property) { 4 if (COLUMN_NAMES[1].equals(property)) { 5 return ((Integer) element).toString(); 6 } 7 return null; 8 } /* ...code missed ...*/ } Методът определя стойността на дадената колона. В дадения пример задължително трябва да върен низ. Ред 5 извършва преобразуването от обект Integer към String. 51 Кирил Митов @ TUES
  • 52. TableViewer - Редактиране ICellModifier - modify(...) 1 fTableViewer.setCellModifier(new ICellModifier() { 2 public void modify(Object element, String property, Object value) { 3 if (element instanceof TableItem && value != null) { 4 int index = ((TableItem) element). getParent(). indexOf((TableItem) element); 5 if (COLUMN_NAMES[1].equals(property)) { 6 fInput[index] = Integer.parseInt((String) value); 7 } 8 fTableViewer.refresh(); }} }); 52 Кирил Митов @ TUES
  • 53. TableViewer - Редактиране ICellModifier - modify(...) 3 if (element instanceof TableItem && value != null) { 4 int index = ((TableItem) element). getParent(). indexOf((TableItem) element); Ред 3: Проверка за коректност на предадените данни. Предаденият за редакция елемент трябва да е от тип TableItem. Новата стойност value не трябва да е null. (Възможно е да е null ако се извърши невалидно въвеждане.) Ред4: TableItem представлява ред от таблицата. В ред 4 намираме индекса на този ред. Този индекс ни е необходим, за да промениме стойността във входния масив. Посочения тук подход се отнася само за разработвания пример. Възможни са други решения. 53 Кирил Митов @ TUES
  • 54. TableViewer - Редактиране ICellModifier - modify(...) 5 if (COLUMN_NAMES[1].equals(property)) { 6 fInput[index] = Integer.parseInt((String) value); 7 } 8 fTableViewer.refresh(); }} Ред 5: Проверка за колоната. Ред 6: Нововъведената от потребителя стойност се предава чрез параметъра value. Тъй като вече е намерен индексът на редактирания елемент се променя стойността във входния масив. Ред 8: Входните данни са променени. Следователно таблицата трябва да се обнови. Обновяването се извършва чрез метода fTableViewer.refresh() 54 Кирил Митов @ TUES
  • 55. TableViewer - Редактиране Разработеният viewer дава възможност за редакция и валидация на редактираните стойностти. След промяната на някое число таблицата се обновява и новите стойности се изписват. 55 Кирил Митов @ TUES
  • 56. Обобщение  JFace предоставя viewer-и. Тези viewer-и се зползват като обвивка на обектите и улесняват значително тяхното графично изобразяване.  JFace не предоставя само viewer-и. Налични са още магьосници (wizards), диалогови прозорци (dialogs), класове улесняващи текстообработката и др.  JFace не е графична библиотека и няма за цел да замени SWT, а да предостави допълнителни улеснения на програмиста при използването на SWT. Възможна е реализацията на графично приложение и без JFace. 56 Кирил Митов @ TUES
  • 57. Copyright This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 2.5 Bulgaria License. To view a copy of this license, visit http:// creativecommons.org/licenses/by-nc-sa/2.5/bg/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. 57 Кирил Митов @ TUES