SlideShare a Scribd company logo
Title



    Editors @ Tues




1             Кирил Митов @ TUES
Editors

    Основният начин за създаване и модифициране на ресурси в Eclipse
    са Редакторите. Съществуват значителен брой редактори от най-
    простите текстови редактори до по-сложни редактори включващи
    няколко страници.
    Пример за такъв редактор е редакторът за MANIFEST.MF и plugin.xml.
    В този случай два различни файла се редактират едновременно с
    един и същи редактор.
    Всеки plugin може да предостави редактор като използва същия
    extension point както всички други редактори.

    Редакторите следват следния цикъл на живот:
       Отваряне на файл -> Редактиране -> Затваряне.




2                                                  Кирил Митов @ TUES
Редактори




3               Кирил Митов @ TUES
Редактори




4               Кирил Митов @ TUES
Редактори




5               Кирил Митов @ TUES
Title

    Пример:
    Да се изгради редактор редактиращ списък от низове.
    Редакторът трябва да работи с файлове с разширение .listeditor.
    Във визуалната си част редакторът ще изобразява низовете като
    списък. Към списъка може да се добавят и изтриват низове.
    Действията ще се извършват чрез избор от контекстно меню.




6                                                  Кирил Митов @ TUES
Title




7           Кирил Митов @ TUES
Title

    Използваме следния extension point
       <extension
             point="org.eclipse.ui.editors">
          <editor

    class="org.elsys.pluginsample.editor.ListEditor"
                extensions="listeditor"
                icon="icons/sample.gif"
                id="org.elsys.pluginsample.editor1"
                name="Elsys List Editor">
          </editor>
       </extension>

    class – класът реализиращ редактора. Трябва да е наследник на
    org.eclipse.ui.IEditorPart
    extension – разширението на файловете, които може да се отварят с
    този редактор
    name – име подходящо за потребителя.


8                                                  Кирил Митов @ TUES
Зависимости

    В реализирането на редактора ще използваме част от
    предоставените от Eclipse класове.

    Необходимо е да добавиме следните зависимости към MANIFEST.MF

    Require-Bundle : org.eclipse.core.runtime,
     org.eclipse.ui,
     org.eclipse.ui.ide,
     org.eclipse.core.resources




9                                                 Кирил Митов @ TUES
ListEditor

 ListEditor
 Логиката на редактора се реализира от класа
 org.elsys.pluginsample.editor.ListEditor.
 Класът трябва да имплементира org.eclipse.ui.IEditorPart.
 IEditorPart има подразбираща се изплементация, от която може да се
 възползваме – org.eclipse.ui.part.EditorPart




10                                              Кирил Митов @ TUES
ListEditor


 public   class ListEditor extends EditorPart {

     private List<String> fContent;

     private boolean fIsDirty;

     private ListViewer fViewer;

     private AddAction fAddAction;

     private DeleteAction fDeleteAction;

     private IFile fInputFile;

     /* ... code missed ... */
 }



11                                         Кирил Митов @ TUES
ListEditor

      fContent – списъкът от низове, който искаме да редактираме

      fIsDirty – показва дали файлът е редактиран и може ли да се
       запамети.

      fViewer – променлива от тип
       org.eclipse.jface.viewers.ListViewer          . Ще използваме
       този viewer, за да изобразим списъка fContent

      fAddAction, fDeleteAction – създадени от нас класове извършващи
       добавяне/изтриване на низ от списъка

      fInputFile – поле от тип org.eclipse.core.resources.IFile
       изобразяващо текущо редактирания файл. Посредством това
       поле можем да достъпим файла, неговото съдържание, родител,
       път до файла и др.




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

 public class ListEditor extends EditorPart {
    public void doSave(IProgressMonitor monitor) { }
    private IWorkspaceRunnable createFileSaveRunnable() { }
    public void doSaveAs() {}
    public ListViewer getViewer() { }
    public List<String> getContent() { }
    public void init(IEditorSite site, IEditorInput input)
          throws PartInitException { }
    public boolean isDirty() {}
    public boolean isSaveAsAllowed() { }
    public void setDirty() {}
    public void createPartControl(Composite parent) { }
    private void createActions() {}
    private void createContextMenu() { }
    private void fillContextMenu(IMenuManager menuMgr) { }
    protected void fillBody(Composite parent) { }
    public void setFocus() {}
 }


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


      public void doSaveAs() {} - Методът се използва ако
       изскаме да дадем възможност на редактора да запаметява
       съдържанието под нов файл.
       public boolean isSaveAsAllowed() {
           return false;
       } -Редакторът намя да поддържа Save As
      public ListViewer getViewer() {
       return fViewer;
       }
       public List<String> getContent() {
          return fContent;
       }
       Методи за достъп да съответните полета от класа

      public void setFocus() {}- Извиква се от средата когато
       редакторът получи фокуса на мишката и клавиетурата.



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

      public boolean isDirty() {
         return fIsDirty;
      }
      public void setDirty() {
         fIsDirty = true;
         firePropertyChange(IEditorPart.PROP_DIRTY);
      }
      Файлът е редактиран. Необходимо е неактивният Save бутон в
       лентата с инструменти да стане активен.
      Необходимо е менюто File->Save да стане активно.
      Необходимо е в прозореца на редактора да се изобрази „ * “.
      Добавяме метода setDirty(), който уведомява „всички
       интересуващи се“ за това, че състоянието на редактора се е
       променило.
      Методът isDirty() ще бъде извикан, когато трябва да се определи
       състоянието на Save менюто. Ако методът върне true то менюто
       ще е активно.

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

 public   void init(IEditorSite site, IEditorInput input)
       throws PartInitException {
    fInputFile = (IFile) input.getAdapter(IFile.class);
    if (fInputFile == null)
       throw new IllegalArgumentException(
              "The input must be adaptable to IFile");
    try {
       InputStream in = fInputFile.getContents();
       ObjectInputStream objectStream = new
 ObjectInputStream(in);
       fContent = (List<String>) objectStream.readObject();
    } catch (Exception e) {
       e.printStackTrace();
       fContent = new ArrayList<String>();
    }
    fIsDirty = false;
    setSite(site);
    setInput(input);
 }

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

 Методът init е първият, който ще се извика в работата на редактора.
 Има за цел да инициализира редактора и да зададе входните му
 данни на база получения обект input. Тъй като нашият редактор
 работи с файлове проверяваме дали полученият обект може да се
 адаптира към обект от тип IFile.

     fInputFile = (IFile) input.getAdapter(IFile.class);
 При отварянето си редакторът трябва да е „чист“ - не може да се
 извърши запаметяване.

     fIsDirty = false;
     setSite(site);
     setInput(input);

 Базовият клас изисква да извикаме и методите setSite() и setInput().




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

 Следващият метод, който ще се извика след init() е createPartControl()

 public  void createPartControl(Composite parent) {
       Composite composite = new Group(parent, SWT.NONE);
       composite.setLayout(new GridLayout(1, false));
       composite.setLayoutData(new
 GridData(GridData.FILL));
       fillBody(composite);
       createActions();
       createContextMenu();
 }

 Методът има за цел да създаде визуалната част на редактора.

 Методите fillBody(), createActions(), createContextMenu() ще бъдат
 допълнени в процеса на разработка.




18                                                 Кирил Митов @ TUES
ListEditor

 protected void fillBody(Composite parent) {
    ListViewer viewer = new ListViewer(parent, SWT.BORDER |
 SWT.SINGLE);
    GridData data = new GridData(GridData.FILL_BOTH);
    viewer.getList().setLayoutData(data);
    viewer.setContentProvider(new ListContentProvider());
    viewer.setLabelProvider(new LabelProvider());
    viewer.setInput(fContent);
    fViewer = viewer;
 }

 Методът fillBody() създава нов viewer от тип ListViewer.

 За ContentProvider - ще създадем клас ListContentProvider.

 За LabelProvider - Използваме
 org.eclipse.jface.viewers.LabelProvider, който по
 подразбиране се обръща към метода toString() на подадените му
 обекти. Тази функционалност ни е достатъчна.

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

 private static class ListContentProvider implements
          IStructuredContentProvider {

       public Object[] getElements(Object inputElement) {
          if (inputElement instanceof List) {
             List list = (List) inputElement;
             return list.toArray(new Object[list.size()]);
          }
          throw new IllegalArgumentException("Unsupported
 input element");
       }

     /* ... code missed ... */
 }




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

 private void createActions() {
       fAddAction = new AddAction(this, fContent, fViewer);
       fDeleteAction = new DeleteAction(this, fContent,
 fViewer);

 }

 Логиката за добавяне и изтриване на низ от списъка ще бъде
 капсулирана в отделни класове.

 Методът createActions() е добавен от нас и има за цел да
 инициализира обектите fAddAction и fDeleteAction.




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

 private void createContextMenu() {
    MenuManager menuMgr = new MenuManager("#PopupMenu");
    menuMgr.setRemoveAllWhenShown(true);
    menuMgr.addMenuListener(new IMenuListener() {
        public void menuAboutToShow(IMenuManager m) {
           ListEditor.this.fillContextMenu(m);
        }
    });
    org.eclipse.swt.widgets.List list = fViewer.getList();
    Menu menu = menuMgr.createContextMenu(list);
    list.setMenu(menu);
    getSite().registerContextMenu(menuMgr, fViewer);
 }

 Редакцията ще се извършва посредством действия от контексното
 меню. Методът createContextMenu() има за цел да създаде това
 меню и да го регистрира в „сайта“ на редактора. Всеки редактор се
 намира в съответния контейтер предоставен от средата. Този
 контейнер се нарича „сайт – site“ и може да бъде достъпен чрез
 getSite().
22                                              Кирил Митов @ TUES
ListEditor

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

 Това се извършва от метода fillContextMenu(). Този метод се вика
 преди всяко показване на менюто.

 Това ни позвалява да променяме характеристиките и броя на
 действията показани в менюто на база на някакво условие.

 private void fillContextMenu(IMenuManager menuMgr) {
       menuMgr.add(fAddAction);
       menuMgr.add(fDeleteAction);
       menuMgr.add(new
 Separator(IWorkbenchActionConstants.MB_ADDITIONS));
 }




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

 Методът doSave() ще се извика при запаметяване на файла.

 public   void doSave(IProgressMonitor monitor) {
       IWorkspaceRunnable runnable =
 createFileSaveRunnable();
    try {
       ResourcesPlugin.getWorkspace().run(runnable,
 monitor);
       fIsDirty = false;
       firePropertyChange(IEditorPart.PROP_DIRTY);
    } catch (CoreException e) {
       e.printStackTrace();
    }
 }




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

 Eclipse е отворена платформа. Броят на plugin-ите е неограничен.
 Неограничена е и тяхната функционалност и действия. Всички plugin-
 и са равнопоставени.

 Всички разработвани проекти стоят в така наречения „workspace“.
 Всяка инстанция на платформата разполага само с един workspace.
 Следователно възможно е извършване на асинхронна промяна на
 едни и същи данни от страна на различни plugin-и, което ще доведе
 до загуба на информация.

 Един от подходите за решаване на този проблем е докато един plugin
 променя workspace-а всики останали да чакат.
 Организира се опашка от заявки за промяна на workspace-а. Такава
 заявка трябва да е от тип
 org.eclipse.core.resources.IWorkspaceRunnable. Достъпът до
 workspace-а се извършва чрез ResourcesPlugin.getWorkspace().

 Методът ResourcesPlugin.getWorkspace().run() и синхронен за
 извикващата нишка и я блокира до приключването на неговата
 работа.
25                                              Кирил Митов @ TUES
ListEditor

 След като заявката приключи е необходимо да се съобщи на „всички
 интересуващи се“ ще състоянието е променено
     fIsDirty = false;
     firePropertyChange(IEditorPart.PROP_DIRTY);


 Добавяме метода createFileSaveRunnable(), който ще използваме
 да създаваме заявки за запаметяване на файла.

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




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

 private IWorkspaceRunnable createFileSaveRunnable() {
     IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
         public void run(IProgressMonitor monitor) throws CoreException {
             try {
                 monitor.beginTask("Saving file...", 10);
                 monitor.worked(2);
                 if (monitor.isCanceled())
                     throw new OperationCanceledException();
                 ByteArrayOutputStream os = new ByteArrayOutputStream();
                 ObjectOutputStream oos = new ObjectOutputStream(os);
                 oos.writeObject(fContent);
                 ByteArrayInputStream is = new
 ByteArrayInputStream(os.toByteArray());
                 oos.close();
                 os.close();
                 fInputFile.setContents(is, IResource.FORCE, new
 SubProgressMonitor(monitor, 9));
             } catch (Exception e) {
                 e.printStackTrace();
             } finally {
                 monitor.done();
             }
         }
     };
     return runnable;
 }
27                                                   Кирил Митов @ TUES
ListEditor

 Съдържанието на списъка fContent трябва да се запамети във
 файла. За целта използваме метода IFile.setContents().

 Необходимо е преди това да представиме съдържанието, което
 искаме да запишем като обект от тип InputStream.
     ByteArrayOutputStream os = new ByteArrayOutputStream();
     ObjectOutputStream oos = new ObjectOutputStream(os);
     oos.writeObject(fContent);
     ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
     oos.close();
     os.close();
     fInputFile.setContents(is, IResource.FORCE, new
                                           SubProgressMonitor(monitor, 9));




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

 След като стартираме plugin-а трябва да създадем нов проект.
 File->New->Project. Даваме име на проекта – примерно SampleProject.

 След това създаваме нов файл в този проект изпозвайки File->New-
 >File. Важното е файлът да е с разширение „listeditor“.

 Създаденият файл може да се отвори с няколко редактора –
 включително и с обикновен текстов редактор. Може да определим
 желания редактор чрез менюто Open With от контексното меню за
 дадения файл.




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




30            Кирил Митов @ TUES
Упражнение

 Използване на готовия код:

 Проект съдържащ класовете ListEditor, AddAction, DeleteAction.

 Необходимо е да добавите:

      зависимостите в MANIFEST.MF

      необходимия extension point в plugin.xml

      липсващите методи и полета в ListEditor




31                                                Кирил Митов @ 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.




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

More Related Content

PDF
Eclipse Editors@TUES (Part 2)
PDF
JFace@TUES
PPT
Water Walk
PPT
The NAILS Mission (Unit 5 - Future Job)
PDF
Eclipse Overview@TUES
ODP
Open Source SOA@OpenFest.org
PDF
Eclipse Modeling Framework@TUES
PPT
JPicus@ESE
Eclipse Editors@TUES (Part 2)
JFace@TUES
Water Walk
The NAILS Mission (Unit 5 - Future Job)
Eclipse Overview@TUES
Open Source SOA@OpenFest.org
Eclipse Modeling Framework@TUES
JPicus@ESE
Ad

Eclipse Editors@TUES (Part1)

  • 1. Title Editors @ Tues 1 Кирил Митов @ TUES
  • 2. Editors Основният начин за създаване и модифициране на ресурси в Eclipse са Редакторите. Съществуват значителен брой редактори от най- простите текстови редактори до по-сложни редактори включващи няколко страници. Пример за такъв редактор е редакторът за MANIFEST.MF и plugin.xml. В този случай два различни файла се редактират едновременно с един и същи редактор. Всеки plugin може да предостави редактор като използва същия extension point както всички други редактори. Редакторите следват следния цикъл на живот: Отваряне на файл -> Редактиране -> Затваряне. 2 Кирил Митов @ TUES
  • 3. Редактори 3 Кирил Митов @ TUES
  • 4. Редактори 4 Кирил Митов @ TUES
  • 5. Редактори 5 Кирил Митов @ TUES
  • 6. Title Пример: Да се изгради редактор редактиращ списък от низове. Редакторът трябва да работи с файлове с разширение .listeditor. Във визуалната си част редакторът ще изобразява низовете като списък. Към списъка може да се добавят и изтриват низове. Действията ще се извършват чрез избор от контекстно меню. 6 Кирил Митов @ TUES
  • 7. Title 7 Кирил Митов @ TUES
  • 8. Title Използваме следния extension point <extension point="org.eclipse.ui.editors"> <editor class="org.elsys.pluginsample.editor.ListEditor" extensions="listeditor" icon="icons/sample.gif" id="org.elsys.pluginsample.editor1" name="Elsys List Editor"> </editor> </extension> class – класът реализиращ редактора. Трябва да е наследник на org.eclipse.ui.IEditorPart extension – разширението на файловете, които може да се отварят с този редактор name – име подходящо за потребителя. 8 Кирил Митов @ TUES
  • 9. Зависимости В реализирането на редактора ще използваме част от предоставените от Eclipse класове. Необходимо е да добавиме следните зависимости към MANIFEST.MF Require-Bundle : org.eclipse.core.runtime, org.eclipse.ui, org.eclipse.ui.ide, org.eclipse.core.resources 9 Кирил Митов @ TUES
  • 10. ListEditor ListEditor Логиката на редактора се реализира от класа org.elsys.pluginsample.editor.ListEditor. Класът трябва да имплементира org.eclipse.ui.IEditorPart. IEditorPart има подразбираща се изплементация, от която може да се възползваме – org.eclipse.ui.part.EditorPart 10 Кирил Митов @ TUES
  • 11. ListEditor public class ListEditor extends EditorPart { private List<String> fContent; private boolean fIsDirty; private ListViewer fViewer; private AddAction fAddAction; private DeleteAction fDeleteAction; private IFile fInputFile; /* ... code missed ... */ } 11 Кирил Митов @ TUES
  • 12. ListEditor  fContent – списъкът от низове, който искаме да редактираме  fIsDirty – показва дали файлът е редактиран и може ли да се запамети.  fViewer – променлива от тип org.eclipse.jface.viewers.ListViewer . Ще използваме този viewer, за да изобразим списъка fContent  fAddAction, fDeleteAction – създадени от нас класове извършващи добавяне/изтриване на низ от списъка  fInputFile – поле от тип org.eclipse.core.resources.IFile изобразяващо текущо редактирания файл. Посредством това поле можем да достъпим файла, неговото съдържание, родител, път до файла и др. 12 Кирил Митов @ TUES
  • 13. ListEditor public class ListEditor extends EditorPart { public void doSave(IProgressMonitor monitor) { } private IWorkspaceRunnable createFileSaveRunnable() { } public void doSaveAs() {} public ListViewer getViewer() { } public List<String> getContent() { } public void init(IEditorSite site, IEditorInput input) throws PartInitException { } public boolean isDirty() {} public boolean isSaveAsAllowed() { } public void setDirty() {} public void createPartControl(Composite parent) { } private void createActions() {} private void createContextMenu() { } private void fillContextMenu(IMenuManager menuMgr) { } protected void fillBody(Composite parent) { } public void setFocus() {} } 13 Кирил Митов @ TUES
  • 14. ListEditor  public void doSaveAs() {} - Методът се използва ако изскаме да дадем възможност на редактора да запаметява съдържанието под нов файл. public boolean isSaveAsAllowed() { return false; } -Редакторът намя да поддържа Save As  public ListViewer getViewer() { return fViewer; } public List<String> getContent() { return fContent; } Методи за достъп да съответните полета от класа  public void setFocus() {}- Извиква се от средата когато редакторът получи фокуса на мишката и клавиетурата. 14 Кирил Митов @ TUES
  • 15. ListEditor public boolean isDirty() { return fIsDirty; } public void setDirty() { fIsDirty = true; firePropertyChange(IEditorPart.PROP_DIRTY); }  Файлът е редактиран. Необходимо е неактивният Save бутон в лентата с инструменти да стане активен.  Необходимо е менюто File->Save да стане активно.  Необходимо е в прозореца на редактора да се изобрази „ * “.  Добавяме метода setDirty(), който уведомява „всички интересуващи се“ за това, че състоянието на редактора се е променило.  Методът isDirty() ще бъде извикан, когато трябва да се определи състоянието на Save менюто. Ако методът върне true то менюто ще е активно. 15 Кирил Митов @ TUES
  • 16. ListEditor public void init(IEditorSite site, IEditorInput input) throws PartInitException { fInputFile = (IFile) input.getAdapter(IFile.class); if (fInputFile == null) throw new IllegalArgumentException( "The input must be adaptable to IFile"); try { InputStream in = fInputFile.getContents(); ObjectInputStream objectStream = new ObjectInputStream(in); fContent = (List<String>) objectStream.readObject(); } catch (Exception e) { e.printStackTrace(); fContent = new ArrayList<String>(); } fIsDirty = false; setSite(site); setInput(input); } 16 Кирил Митов @ TUES
  • 17. ListEditor Методът init е първият, който ще се извика в работата на редактора. Има за цел да инициализира редактора и да зададе входните му данни на база получения обект input. Тъй като нашият редактор работи с файлове проверяваме дали полученият обект може да се адаптира към обект от тип IFile. fInputFile = (IFile) input.getAdapter(IFile.class); При отварянето си редакторът трябва да е „чист“ - не може да се извърши запаметяване. fIsDirty = false; setSite(site); setInput(input); Базовият клас изисква да извикаме и методите setSite() и setInput(). 17 Кирил Митов @ TUES
  • 18. ListEditor Следващият метод, който ще се извика след init() е createPartControl() public void createPartControl(Composite parent) { Composite composite = new Group(parent, SWT.NONE); composite.setLayout(new GridLayout(1, false)); composite.setLayoutData(new GridData(GridData.FILL)); fillBody(composite); createActions(); createContextMenu(); } Методът има за цел да създаде визуалната част на редактора. Методите fillBody(), createActions(), createContextMenu() ще бъдат допълнени в процеса на разработка. 18 Кирил Митов @ TUES
  • 19. ListEditor protected void fillBody(Composite parent) { ListViewer viewer = new ListViewer(parent, SWT.BORDER | SWT.SINGLE); GridData data = new GridData(GridData.FILL_BOTH); viewer.getList().setLayoutData(data); viewer.setContentProvider(new ListContentProvider()); viewer.setLabelProvider(new LabelProvider()); viewer.setInput(fContent); fViewer = viewer; } Методът fillBody() създава нов viewer от тип ListViewer. За ContentProvider - ще създадем клас ListContentProvider. За LabelProvider - Използваме org.eclipse.jface.viewers.LabelProvider, който по подразбиране се обръща към метода toString() на подадените му обекти. Тази функционалност ни е достатъчна. 19 Кирил Митов @ TUES
  • 20. ListEditor private static class ListContentProvider implements IStructuredContentProvider { public Object[] getElements(Object inputElement) { if (inputElement instanceof List) { List list = (List) inputElement; return list.toArray(new Object[list.size()]); } throw new IllegalArgumentException("Unsupported input element"); } /* ... code missed ... */ } 20 Кирил Митов @ TUES
  • 21. ListEditor private void createActions() { fAddAction = new AddAction(this, fContent, fViewer); fDeleteAction = new DeleteAction(this, fContent, fViewer); } Логиката за добавяне и изтриване на низ от списъка ще бъде капсулирана в отделни класове. Методът createActions() е добавен от нас и има за цел да инициализира обектите fAddAction и fDeleteAction. 21 Кирил Митов @ TUES
  • 22. ListEditor private void createContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager m) { ListEditor.this.fillContextMenu(m); } }); org.eclipse.swt.widgets.List list = fViewer.getList(); Menu menu = menuMgr.createContextMenu(list); list.setMenu(menu); getSite().registerContextMenu(menuMgr, fViewer); } Редакцията ще се извършва посредством действия от контексното меню. Методът createContextMenu() има за цел да създаде това меню и да го регистрира в „сайта“ на редактора. Всеки редактор се намира в съответния контейтер предоставен от средата. Този контейнер се нарича „сайт – site“ и може да бъде достъпен чрез getSite(). 22 Кирил Митов @ TUES
  • 23. ListEditor Преди менюто да бъде показано то трябва да бъде запълнено със съответните елементи. Това се извършва от метода fillContextMenu(). Този метод се вика преди всяко показване на менюто. Това ни позвалява да променяме характеристиките и броя на действията показани в менюто на база на някакво условие. private void fillContextMenu(IMenuManager menuMgr) { menuMgr.add(fAddAction); menuMgr.add(fDeleteAction); menuMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } 23 Кирил Митов @ TUES
  • 24. ListEditor Методът doSave() ще се извика при запаметяване на файла. public void doSave(IProgressMonitor monitor) { IWorkspaceRunnable runnable = createFileSaveRunnable(); try { ResourcesPlugin.getWorkspace().run(runnable, monitor); fIsDirty = false; firePropertyChange(IEditorPart.PROP_DIRTY); } catch (CoreException e) { e.printStackTrace(); } } 24 Кирил Митов @ TUES
  • 25. ListEditor Eclipse е отворена платформа. Броят на plugin-ите е неограничен. Неограничена е и тяхната функционалност и действия. Всички plugin- и са равнопоставени. Всички разработвани проекти стоят в така наречения „workspace“. Всяка инстанция на платформата разполага само с един workspace. Следователно възможно е извършване на асинхронна промяна на едни и същи данни от страна на различни plugin-и, което ще доведе до загуба на информация. Един от подходите за решаване на този проблем е докато един plugin променя workspace-а всики останали да чакат. Организира се опашка от заявки за промяна на workspace-а. Такава заявка трябва да е от тип org.eclipse.core.resources.IWorkspaceRunnable. Достъпът до workspace-а се извършва чрез ResourcesPlugin.getWorkspace(). Методът ResourcesPlugin.getWorkspace().run() и синхронен за извикващата нишка и я блокира до приключването на неговата работа. 25 Кирил Митов @ TUES
  • 26. ListEditor След като заявката приключи е необходимо да се съобщи на „всички интересуващи се“ ще състоянието е променено fIsDirty = false; firePropertyChange(IEditorPart.PROP_DIRTY); Добавяме метода createFileSaveRunnable(), който ще използваме да създаваме заявки за запаметяване на файла. Отделянето кода за изпълнение на заявката и кода за създаване на заявката позволяват по-лесна промяна на функционалността и по- добро капсулиране на данните. 26 Кирил Митов @ TUES
  • 27. ListEditor private IWorkspaceRunnable createFileSaveRunnable() { IWorkspaceRunnable runnable = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { try { monitor.beginTask("Saving file...", 10); monitor.worked(2); if (monitor.isCanceled()) throw new OperationCanceledException(); ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(fContent); ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); oos.close(); os.close(); fInputFile.setContents(is, IResource.FORCE, new SubProgressMonitor(monitor, 9)); } catch (Exception e) { e.printStackTrace(); } finally { monitor.done(); } } }; return runnable; } 27 Кирил Митов @ TUES
  • 28. ListEditor Съдържанието на списъка fContent трябва да се запамети във файла. За целта използваме метода IFile.setContents(). Необходимо е преди това да представиме съдържанието, което искаме да запишем като обект от тип InputStream. ByteArrayOutputStream os = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(fContent); ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); oos.close(); os.close(); fInputFile.setContents(is, IResource.FORCE, new SubProgressMonitor(monitor, 9)); 28 Кирил Митов @ TUES
  • 29. ListEditor След като стартираме plugin-а трябва да създадем нов проект. File->New->Project. Даваме име на проекта – примерно SampleProject. След това създаваме нов файл в този проект изпозвайки File->New- >File. Важното е файлът да е с разширение „listeditor“. Създаденият файл може да се отвори с няколко редактора – включително и с обикновен текстов редактор. Може да определим желания редактор чрез менюто Open With от контексното меню за дадения файл. 29 Кирил Митов @ TUES
  • 30. ListEditor 30 Кирил Митов @ TUES
  • 31. Упражнение Използване на готовия код: Проект съдържащ класовете ListEditor, AddAction, DeleteAction. Необходимо е да добавите:  зависимостите в MANIFEST.MF  необходимия extension point в plugin.xml  липсващите методи и полета в ListEditor 31 Кирил Митов @ TUES
  • 32. 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. 32 Кирил Митов @ TUES