Nyílt fejlesztőrendszerek Graphical Editing Framework
GEF célja Grafikus szerkesztőprogramok Grafikus szerkesztőprogramok Integráció az Eclipse környezetbe Integráció az Eclipse környezetbe Tetszőleges modell megjelenítése Tetszőleges modell megjelenítése Magas absztrakciós szint Magas absztrakciós szint
Példa
GEF felépítése Interakció (MVC) Interakció (MVC) Modell nézet leképzés Modell nézet leképzés Eclipse integráció Eclipse integráció Megjelenítés Megjelenítés Elemek elrendezése Elemek elrendezése Nagyítás Nagyítás Natív (SWT) réteg Natív (SWT) réteg
MVC séma Modell – Nézet – Vezérlő Modell – Nézet – Vezérlő Adatok tárolása és megjelenítése külön Adatok tárolása és megjelenítése külön Modell: adatok tárolása Modell: adatok tárolása Nézet: grafikus megjelenítés Nézet: grafikus megjelenítés Vezérlő: felhasználói interakció Vezérlő: felhasználói interakció Elterjedt: JSF, Swing, JFace, MFC Elterjedt: JSF, Swing, JFace, MFC
MVC a gyakorlatban MODEL L NÉZE T Felhasználó 1. felhasználói akció Vezérlő 2. modell módosítás 3. visszajelzés 4. nézet frissítése 5. modell lekérdezése 6. megjelenítés
MVC részei a GEF-ben I. Modell: tetszőleges Modell: tetszőleges EMF, Java osztályok, adatbázis EMF, Java osztályok, adatbázis Hierarchikus felépítés (gyökeres fa) Hierarchikus felépítés (gyökeres fa) Támogatnia kell az értesítéseket Támogatnia kell az értesítéseket Jelentés a vezérlőnek, ha módosítás történt Jelentés a vezérlőnek, ha módosítás történt 1 modell több nézet esetén fontos 1 modell több nézet esetén fontos Pl. EMF Notification Framework Pl. EMF Notification Framework Üzleti modell: struktúra, adatok Üzleti modell: struktúra, adatok Nézeti modell: megjelenítési információk Nézeti modell: megjelenítési információk Pl. pozíció, méret. Pl. pozíció, méret.
Egyszerű modell public class ElsoModel { private String name; private Rectangle bounds; public String getName() { return name; } public String getName() { return name; } public void setName(String n) { name = n; } public void setName(String n) { name = n; } public Rectangle getBounds() { return bounds; } public Rectangle getBounds() { return bounds; } public void setBounds(Rectangle r) { bounds = r; } } public void setBounds(Rectangle r) { bounds = r; } } Üzleti modell Nézeti modell
Egyszerű értesítés public interface MyModelListener { public void modelChanged(); } public class ElsoModel {... private List listeners; public ElsoModel() { listeners = new Vector (); } public void addListener(MyModelListener list) { listeners.add(list); } public void removeListener(MyModelListener list) { listeners.remove(list); } private void fireListeners() { for (MyModelListener list : listeners) list.modelChanged(); } }
Push vs. pull értesítés Pull: Csak annyit küld, hogy változás történt Pull: Csak annyit küld, hogy változás történt Gyors, erőforráskímélő Gyors, erőforráskímélő Minden változó attribútumot vizsgálni kell Minden változó attribútumot vizsgálni kell Push: Pontosan megmondjuk, hogy mi változott (pl. új X pozíció = 172) Push: Pontosan megmondjuk, hogy mi változott (pl. új X pozíció = 172) El kell küldeni magát a változást is, lassú El kell küldeni magát a változást is, lassú Könnyen feldolgozható Könnyen feldolgozható
MVC részei a GEF-ben II. Nézet: Draw2D osztályok Nézet: Draw2D osztályok SWT-re épülő grafikus könyvtár SWT-re épülő grafikus könyvtár Egyszerű elemek (címke, téglalap, nyíl) Egyszerű elemek (címke, téglalap, nyíl) Hierarchikus megjelenítés Hierarchikus megjelenítés Alap építőelem: Figure Alap építőelem: Figure GEF nézet = Draw2D Figure példány GEF nézet = Draw2D Figure példány Bármely SWT alkalmazásban használható Bármely SWT alkalmazásban használható Saját üzenetkezelése is van Saját üzenetkezelése is van
Draw2D hierarchia Minden gyerek csak a szülőjén belül Minden gyerek csak a szülőjén belül Gyerekek balról jobbra Gyerekek balról jobbra Pontosan 1 gyökérelem Pontosan 1 gyökérelem
Draw2D LayoutManager Gyerekek elrendezése szülőn belül Gyerekek elrendezése szülőn belül Több beépített, lehet saját is Több beépített, lehet saját is Constraint: Egy gyerek elhelyezésével kapcsolatos kényszer Constraint: Egy gyerek elhelyezésével kapcsolatos kényszer SWT-nél ez volt a LayoutData SWT-nél ez volt a LayoutData Szülő pozíció és méret + LayoutManager + Constraint Gyerek pozíció és méret Szülő pozíció és méret + LayoutManager + Constraint Gyerek pozíció és méret Szülőben kell megadni, nem a gyerekben!!! Szülőben kell megadni, nem a gyerekben!!!
Draw2D LayoutManagerek Top BorderLayoutFlowLayout Bottom Left Right Center ToolbarLayout XYLayout 12,8,20,10 30,20,27, Constraint
Draw2D alapelemek Egyszerű elemek Egyszerű elemek Label, Button, CheckBox, Image Label, Button, CheckBox, Image Geometriai alakzatok Geometriai alakzatok RectangleFigure, Ellipse, Triangle RectangleFigure, Ellipse, Triangle Panel: általános konténer elem Panel: általános konténer elem ScrollPane: görgethető tartalmú elem ScrollPane: görgethető tartalmú elem
Draw2D alapelemek public class Pelda1 extends Figure { public Pelda1() { setOpaque(true); setBackgroundColor(ColorConstants.white); setLayoutManager(new ToolbarLayout()); add(new Label("Label!")); add(new CheckBox("CheckBox!")); add(new Button("Button!")); add(new RectangleFigure()); add(new Ellipse()); add(new RoundedRectangle()); add(new Triangle()); for (int i = 3; i <= 6; i++) ((Figure) getChildren().get(i)).setPreferredSize(-1, 40); } } Alapból minden átlátszó Minden elemnek lehet egy preferrált mérete, LayoutManagerek figyelembe vehetik
Draw2D keretek Minden Figurehöz rendelhető keret Minden Figurehöz rendelhető keret TitleBarBorder: dialógusablak jelleg TitleBarBorder: dialógusablak jelleg LineBorder: egyszerű vonal LineBorder: egyszerű vonal MarginBorder: üres hely MarginBorder: üres hely Keretek egymásba ágyazhatók Keretek egymásba ágyazhatók CompoundBorder CompoundBorder Megosztható Figureök között Megosztható Figureök között
Draw2D keretek public class Example2 extends Figure { public Example2() { setOpaque(true); setBackgroundColor(ColorConstants.white); setLayoutManager(new XYLayout()); TitleBarBorder tb = new TitleBarBorder("TitleBarBorder"); tb.setTextColor(ColorConstants.white); setBorder(new CompoundBorder(new LineBorder(1), tb)); Label lbl = new Label("Címke"); lbl.setBorder(new CompoundBorder( new LineBorder(1), new CompoundBorder( new MarginBorder(2, 10, 20, 30), new LineBorder(ColorConstants.blue, 5)))); add(lbl); setConstraint(lbl, new Rectangle(20, 20, 120, 70)); } } Constraint megadása a szülőben
Draw2D egyéb elemek Nyilak: lásd később Nyilak: lásd később Beépített elemek kombinációja nem mindig elégséges saját elemek Beépített elemek kombinációja nem mindig elégséges saját elemek paintFigure() felülírása kell paintFigure() felülírása kell Tetszőleges SWT rajzoló kód lehet Tetszőleges SWT rajzoló kód lehet
Draw2D saját elem public class Example3 extends Figure protected void paintFigure(Graphics graphics) { Rectangle r = getBounds(); PaletteData pd = new PaletteData(0xff0000, 0xff00, 0xff); pd.redShift = -16; pd.greenShift = -8; pd.blueShift = 0; pd.isDirect = true; ImageData id = new ImageData(r.width, r.height, 24, pd); for (int u = 0; u < r.width; u++) for (int v = 0; v < r.height; v++) { int rc = ((int) ((Math.sin(u * 9.0 / r.width) + Math.cos(v * 7.0 / r.height)) * 256.0)) % 256; id.setPixel(u, v, rc << 16); } Image img = new Image(Display.getCurrent(), id); graphics.drawImage(img, r.getTopLeft()); } }
MVC részei a GEF-ben III. Vezérlő: EditPart osztályok Vezérlő: EditPart osztályok GEF „lelke” GEF „lelke” Kapcsolat a modell és a nézet között Kapcsolat a modell és a nézet között 1 Figure 1 EditPart 1 Figure 1 EditPart 1 modell elem több EditPart is lehet 1 modell elem több EditPart is lehet Minden nézethez egy példány Minden nézethez egy példány Felhasználói akciók kezelése Felhasználói akciók kezelése
GEF szerkesztő lépései Kezdeti nézet felépítése Kezdeti nézet felépítése Modell bejárása, nézet elkészítése Modell bejárása, nézet elkészítése Szerkesztési „szabályok” meghatározása Szerkesztési „szabályok” meghatározása Felhasználói akciók Felhasználói akciók Üzenetek értelmezése a szerkesztési „szabályok” alapján Üzenetek értelmezése a szerkesztési „szabályok” alapján Modell módosítása Modell módosítása Nézetek frissítése Nézetek frissítése
1. Kezdeti nézet felépítése Modell alapján EditPartok létrehozása Modell alapján EditPartok létrehozása EditPartFactory EditPartFactory Nézet Figureök példányosítása Nézet Figureök példányosítása GraphicalEditPart.createFigure() GraphicalEditPart.createFigure() Modell gyökér EditPart hierarchia … … Gyerekek fig … Nézet
EditPartViewer Egy EditPart hierarchia megjelenítéséért felelős Egy EditPart hierarchia megjelenítéséért felelős Elvben hasonló, mint a JFace viewerek Elvben hasonló, mint a JFace viewerek Fa- vagy grafikus nézet Fa- vagy grafikus nézet TreeViewer: tipikusan Outline nézethez TreeViewer: tipikusan Outline nézethez GraphicalViewer: grafikus nézet GraphicalViewer: grafikus nézet ScrollingGraphicalViewer: éppen ez az aktuális javasolt megvalósítás (pár hónapja még nem is létezett ilyen osztály ) ScrollingGraphicalViewer: éppen ez az aktuális javasolt megvalósítás (pár hónapja még nem is létezett ilyen osztály )
EditPartViewer II. Három szükséges alkotóelem Három szükséges alkotóelem EditDomain: GEF alkalmazás „állapota” EditDomain: GEF alkalmazás „állapota” EditPartFactory: modell EditPart leképzés EditPartFactory: modell EditPart leképzés Gyökér modellelem Gyökér modellelem... public void createPartControl(Composite parent) { ScrollingGraphicalViewer sgv = new ScrollingGraphicalViewer(); sgv.setEditDomain(new DefaultEditDomain(this)); sgv.setEditPartFactory(new MyEditPartFactory()); sgv.setContents(model_gyoker_elem); sgv.createControl(parent); }...
EditDomain GEF állapot GEF állapot Aktív eszköz (active tool) Aktív eszköz (active tool) Éppen használt szerkesztő funkció Éppen használt szerkesztő funkció Pl. kijelölés, új elem, törlés Pl. kijelölés, új elem, törlés CommandStack CommandStack Elvégzett módosítások listája Elvégzett módosítások listája Undo / redo támogatáshoz Undo / redo támogatáshoz Használjuk mindig a DefaultEditDomain-t Használjuk mindig a DefaultEditDomain-t
EditPartFactory Modell alapján EditPart generálása Modell alapján EditPart generálása public class ElsoGEFEditPartFactory implements EditPartFactory { public EditPart createEditPart(EditPart context, Object model) { EditPart ep = null; if (model instanceof ElemModel) ep = new ElemEditPart(); else if (model instanceof SzuloModel) ep = new SzuloEditPart(); if (ep != null) ep.setModel(model); return ep; } } Szülő EditPart EditPart tud tárolni egy modell referenciát
Nézet legenerálása EditPart feladata EditPart feladata Sajátunkat célszerű származtatni az AbstractGraphicalEditPart osztályból Sajátunkat célszerű származtatni az AbstractGraphicalEditPart osztályból public class ElemEditPart extends AbstractGraphicalEditPart protected IFigure createFigure() { // Saját Figure létrehozása ElemFigure fig = new ElemFigure(); return fig; }... }
Modell bejárása EditPartViewer tartalma EditPartViewer tartalma EditPartFactory EditPartFactory Modell gyökér eleme Modell gyökér eleme Hogy jutunk el a modell többi részéhez? Hogy jutunk el a modell többi részéhez? EditParton keresztül EditParton keresztül Mindenki megmondja a saját gyerekeit Mindenki megmondja a saját gyerekeit Rekurzívan bejárható az egész modell Rekurzívan bejárható az egész modell Ne legyen benne tartalmazás kör Ne legyen benne tartalmazás kör
Modell bejárása EditPart.getModelChildren() EditPart.getModelChildren() Az EditParthoz tartozó modellelem gyerekeit kell visszaadni listaként Az EditParthoz tartozó modellelem gyerekeit kell visszaadni listaként Lista sorrendje számít nézetek takarása Lista sorrendje számít nézetek takarása public class SzuloEditPart extends AbstractGraphicalEditPart protected List getModelChildren() { // Saját modell lekérdezése SzuloModel szm = ((SzuloModel) getModel()); return szm.getChildren(); }... } EditPartból a saját modell elérése Modell-függő függvény, nem GEF!
Nézet felépítés összefoglalás Modell GraphicalViewer EditPartokFigureök EditPart Factory
Content Pane X modellelem gyerekeinek a nézetei X nézetének a gyerekei X modellelem gyerekeinek a nézetei X nézetének a gyerekei Összetett Figurek esetén nem jó Összetett Figurek esetén nem jó ContentPane: Figure ős X gyerekeinek ContentPane: Figure ős X gyerekeinek EditPartban adhatjuk meg EditPartban adhatjuk meg Saját Figureünkben gondoskodni kell róla Saját Figureünkben gondoskodni kell public IFigure getContentPane() { return ((MyFigure) getFigure()).getGyerekekHelye(); }...
Szerkesztés szereplői I. EditDomain: fogadja az eseményeket az SWT-től, és továbbítja az aktív Toolnak EditDomain: fogadja az eseményeket az SWT-től, és továbbítja az aktív Toolnak Nem végez feldolgozást, csak összefogja egy modell összes nézetét Nem végez feldolgozást, csak összefogja egy modell összes nézetét Tool: egy szerkesztési funkciót jelképez Tool: egy szerkesztési funkciót jelképez Feldolgozza az SWT üzeneteket Feldolgozza az SWT üzeneteket Létrehoz egy (vagy több) Request-et Létrehoz egy (vagy több) Request-et
Szerkesztés szereplői II. Request Request GEF-szintű esemény GEF-szintű esemény Pl. CreateRequest, DeleteRequest Pl. CreateRequest, DeleteRequest Továbbítódik a cél EditParthoz Továbbítódik a cél EditParthoz EditPolicy EditPolicy EditParthoz tartozó „szerkesztési szabály” EditParthoz tartozó „szerkesztési szabály” Request Command leképzés Request Command leképzés 1 EditPart több EditPolicy lehet 1 EditPart több EditPolicy lehet
Szerkesztés szereplői III. Command Command A modell módosítását végzi A modell módosítását végzi Visszavonható (ha megírjuk ) Visszavonható (ha megírjuk ) CommandStack CommandStack Végrehajtott Commandok verme Végrehajtott Commandok verme Ez biztosítja az undo/redo lehetőségét Ez biztosítja az undo/redo lehetőségét EditDomainenként pontosan egy darab EditDomainenként pontosan egy darab Mindig ezen keresztül módosítsunk! Mindig ezen keresztül módosítsunk!
Szerkesztés szereplői IV. EditPart EditPart A saját EditPolicyjai segítségével átalakítja a bejövő Requestet egy Commandá A saját EditPolicyjai segítségével átalakítja a bejövő Requestet egy Commandá Észleli a modell változását az értesítési mechanizmuson keresztül Észleli a modell változását az értesítési mechanizmuson keresztül Modellváltozás esetén frissíti a nézetet, illetve a struktúrát Modellváltozás esetén frissíti a nézetet, illetve a struktúrát
Szerkesztés szereplői V. Action Action Nem GEF-specifikus (JFace) Nem GEF-specifikus (JFace) Nem „grafikus” felhasználói akció Nem „grafikus” felhasználói akció Menüelemek, billentyűlenyomások, toolbar elemek Menüelemek, billentyűlenyomások, toolbar elemek GEF biztosít néhány wrappert, amik lehetővé teszik a CommandStack egyszerű elérését GEF biztosít néhány wrappert, amik lehetővé teszik a CommandStack egyszerű elérését ActionRegistry: actionök listája ActionRegistry: actionök listája Több helyen szereplő azonos actionökhöz Több helyen szereplő azonos actionökhöz Nincs több (lényeges) szereplő Nincs több (lényeges) szereplő
Szerkesztés folyamata Figure Modell CommandStackEditPolicy EditPart Tool SWTEditDomain 1.SWT üzenet 2.SWT üzenet 8.Frissítés 3.Request 4.Request 5.Command 6.Módosítás 7.Értesítés
Tool Beépített Toolok Beépített Toolok SelectionTool, CreationTool, MarqueeTool SelectionTool, CreationTool, MarqueeTool Saját Tool is készíthető Saját Tool is készíthető TargetingTool: Ha van egy cél EditPart TargetingTool: Ha van egy cél EditPart AbstractTool: teljesen általános AbstractTool: teljesen általános Aktív tool módosítása Aktív tool módosítása EditDomain.setActiveTool() EditDomain.setActiveTool() Eszköztár (Palette): lásd később Eszköztár (Palette): lásd később
Request ChangeBoundsRequest: átméretezés ChangeBoundsRequest: átméretezés CreationRequest: elem létrehozása CreationRequest: elem létrehozása Minden Requesthez tartozik egy típus azonosító Minden Requesthez tartozik egy típus azonosító RequestConstants osztályban RequestConstants osztályban REQ_xxx konstansok REQ_xxx konstansok EditPolicyk ez alapján azonosítják EditPolicyk ez alapján azonosítják
EditPolicy Pontosan egy EditParthoz tartozik Pontosan egy EditParthoz tartozik getHost()-al lekérdezhető getHost()-al lekérdezhető 1 EditPart több EditPolicy lehet 1 EditPart több EditPolicy lehet Azonosítás sztring kulcsokkal (EditPolicy.xxx) Azonosítás sztring kulcsokkal (EditPolicy.xxx) Feladatai Feladatai Request Command leképzés Request Command leképzés Command getCommand(Request) Command getCommand(Request) Grafikus visszajelzés a felhasználónak Grafikus visszajelzés a felhasználónak show(Source/Target)Feedback() show(Source/Target)Feedback()
EditPolicy II. Beépített absztrakt ősosztályok Beépített absztrakt ősosztályok Némi előfeldolgozást végeznek a Requesten Némi előfeldolgozást végeznek a Requesten ComponentEditPolicy: törlés ComponentEditPolicy: törlés ContainerEditPolicy: létrehozás ContainerEditPolicy: létrehozás LayoutEditPolicy: átméretezés LayoutEditPolicy: átméretezés XYLayoutEditPolicy: átméretezés, ha az EditPart nézete XYLayoutot használ XYLayoutEditPolicy: átméretezés, ha az EditPart nézete XYLayoutot használ Biztosítja a grafikus visszajelzést Biztosítja a grafikus visszajelzést
EditPolicy példa public class MyLayoutEditPolicy extends XYLayoutEditPolicy { protected Command createAddCommand(EditPart child, Object constraint) { return null; } protected Command createChangeConstraintCommand( EditPart child, Object constraint) { if (child.getModel() instanceof ElemModel && constraint instanceof Rectangle) return new MyResizeCommand(((ElemModel) child.getModel()), ((Rectangle) constraint)); return null; } protected Command getCreateCommand(CreateRequest request) { return null; } protected Command getDeleteDependantCommand(Request req) { return null; } } XYLayout szülő Átméretezés Saját Command
Command példa public class MyResizeCommand extends Command { ElemModel model; Rectangle newsize, oldsize; public MyResizeCommand(ElemModel m, Rectangle r) { model = m; newsize = r; } public boolean canExecute() { return (r.width >= 40 && r.height >= 40); } public void execute() { oldsize = model.getBounds(); model.setBounds(newsize); } public boolean canUndo() { return true; } public void undo() { model.setBounds(oldsize); } } Végrehajthatóság feltétele Modell függvény
EditPart részei EditPolicyk telepítése EditPolicyk telepítése createEditPolicies(), installEditPolicy() createEditPolicies(), installEditPolicy() Modell figyelése Modell figyelése activate(), deactivate() activate(), deactivate() Nézet frissítése Nézet frissítése refreshVisuals(): nem strukturális módosítás refreshVisuals(): nem strukturális módosítás refreshChildren(): gyerekek listája változik refreshChildren(): gyerekek listája változik
EditPart példa I. public class SzuloEditPart extends AbstractGraphicalEditPart implements MyModelListener { protected IFigure createFigure() { return new SzuloView(); } protected void createEditPolicies() { installEditPolicy(EditPolicy.LAYOUT_ROLE, new MyLayoutEditPolicy()); } protected List getModelChildren() { return ((SzuloModel) getModel()).getChildren(); } protected void refreshVisuals() { ((SzuloView) getFigure()).setLabel( ((SzuloModel) getModel()).getName()); }... EditPolicy ID EditPolicy telepítése Nézet frissítése
EditPart példa II.... public void activate() { super.activate(); ((SzuloModel) getModel()).addListener(this); } public void deactivate() { ((SzuloModel) getModel()).removeListener(this); super.deactivate(); } public void modelChanged() { refreshVisuals(); refreshChildren(); } } Modellfigyelés kezdete Modellfigyelés vége Modell ezt hívja (vö. MyModelListener) Gyerekek frissítése
Mit kell nekünk megírni I. Modell kód, értesítéssel Modell kód, értesítéssel Generáltatható EMF-el (jövő hét) Generáltatható EMF-el (jövő hét) Nézet osztályok Nézet osztályok EditPart osztályok 1. EditPart osztályok 1. Modell megjelenítés Modell megjelenítés createFigure(), refreshVisuals() createFigure(), refreshVisuals() Modell változás figyelés Modell változás figyelés activate(), deactivate() activate(), deactivate()
Mit kell nekünk megírni II. EditPartFactory (modell EditPart) EditPartFactory (modell EditPart) Modell módosító Commandok Modell módosító Commandok Saját EditPolicyk, amik a Commandokat használják Saját EditPolicyk, amik a Commandokat használják Milyen műveleteket engedünk meg Milyen műveleteket engedünk meg EditPart oszályok 2. EditPart oszályok 2. EditPolicyk hozzárendelése EditPolicyk hozzárendelése Editor és tartozékai Editor és tartozékai
Editor készítése Feladatai Feladatai Létrehoz egy EditPartViewert Létrehoz egy EditPartViewert Kezeli a nem grafikus műveleteket Kezeli a nem grafikus műveleteket Actionök (undo/redo is ezek közé tartozik) Actionök (undo/redo is ezek közé tartozik) Létrehozza a menü és toolbar bejegyzéseket Létrehozza a menü és toolbar bejegyzéseket ActionBarContributor (lásd labor) ActionBarContributor (lásd labor) Megoldás Megoldás Saját EditorPart, ezeket mi írjuk meg Saját EditorPart, ezeket mi írjuk meg GraphicalEditor használata GraphicalEditor használata Nem ajánlott, de egyszerű Nem ajánlott, de egyszerű
GraphicalEditor Ősosztály GEFes Eclipse editorokhoz Ősosztály GEFes Eclipse editorokhoz Létrehoz egy ScrollingGraphicalViewer-t Létrehoz egy ScrollingGraphicalViewer-t Létrehoz egy pár általános Actiont Létrehoz egy pár általános Actiont Undo, redo, törlés, nyomtatás, mentés Undo, redo, törlés, nyomtatás, mentés Nem jeleníti meg őket sehol Nem jeleníti meg őket sehol Használjuk az editor készítése közben teszteléshez, kísérletezéshez, de a végső alkalmazásba inkább ne kerüljön Használjuk az editor készítése közben teszteléshez, kísérletezéshez, de a végső alkalmazásba inkább ne kerüljön
GraphicalEditor használata public class ElsoGEFEditor extends GraphicalEditor { public ElsoGEFEditor() { setEditDomain(new DefaultEditDomain(this)); } protected void configureGraphicalViewer() { getGraphicalViewer().setEditPartFactory( new ElsoGEFEditPartFactory()); } public void init(IEditorSite site, IEditorInput input) throws PartInitException { super.init(site, input); // Modell felépítése az input alapján } protected void initializeGraphicalViewer() { getGraphicalViewer().setContents(modell_gyoker); }... } EditDomain kell a konstruktorban! EditPartFactory megadása Megnyitott fájl feldolgozás (Eclipse) Modell gyökérelem megadása
Eszköztár (Palette) Aktív eszköz váltása Aktív eszköz váltása Eszközök grafikus megjelenítése Eszközök grafikus megjelenítése Belül ez is egy külön GEF viewer Belül ez is egy külön GEF viewer PaletteRoot: eszköztár gyökere PaletteRoot: eszköztár gyökere PaletteEntry: eszköztár bejegyzés PaletteEntry: eszköztár bejegyzés PaletteContainer: eszközök csoportja PaletteContainer: eszközök csoportja ToolEntry: egy konkrét eszköz ToolEntry: egy konkrét eszköz
Gyakori ToolEntryk SelectionToolEntry: kijelölés eszköz SelectionToolEntry: kijelölés eszköz MarqueeToolEntry: csoportos kijelölés MarqueeToolEntry: csoportos kijelölés CreationToolEntry: elem létrehozása CreationToolEntry: elem létrehozása Nehézkes használni Nehézkes használni Factory osztály, ez lekérdezhető a Requesten kereszül az EditPolicyban azonosítás Factory osztály, ez lekérdezhető a Requesten kereszül az EditPolicyban azonosítás Minden ToolEntryhez tartozik Minden ToolEntryhez tartozik Név, rövid leírás, kis/nagy ikon Név, rövid leírás, kis/nagy ikon Tool osztály, amit példányosít Tool osztály, amit példányosít
GraphicalEditorWithPalette Olyan GraphicalEditor, ami létrehozza saját magának az eszköztárat Olyan GraphicalEditor, ami létrehozza saját magának az eszköztárat Szintén nem javasolt használni Szintén nem javasolt használni Eszköztárhoz csak egy függvényt kell megírnunk Eszköztárhoz csak egy függvényt kell megírnunk getPaletteRoot() getPaletteRoot()
GraphicalEditorWithPalette példa public class ElsoGEFEditor extends GraphicalEditorWithPalette { protected PaletteRoot getPaletteRoot() { PaletteRoot root = new PaletteRoot(); PaletteGroup sgrp = new PaletteGroup("Selection"); ToolEntry tool = new SelectionToolEntry(); selectionToolGroup.add(tool); root.setDefaultEntry(tool); tool = new MarqueeToolEntry(); selectionToolGroup.add(tool); root.add(selectionToolGroup); root.add(new PaletteSeparator()); root.add(new CreationToolEntry("New Place", "Creates a new Petri net place", new SimpleFactory(PetriPlace.class), MyPlugin.getImageDescriptor(„place.png”), MyPlugin.getImageDescriptor(„place.png”));... return root; }... } Új eszköztár Csoport Elválasztó vonal Factory a létrehozáshoz
Nyilak Hasonlóak a normál objektumokhoz Hasonlóak a normál objektumokhoz Megjelenítés külön (felsőbb) rétegben Megjelenítés külön (felsőbb) rétegben Nyíl mindig látszik, akkor is ha nem kéne Nyíl mindig látszik, akkor is ha nem kéne Van saját EditPartjuk Van saját EditPartjuk AbstractConnectionEditPartból származik AbstractConnectionEditPartból származik Saját EditPolicyk, Requestek,... Saját EditPolicyk, Requestek,... Irányítottak (modell szinten) Irányítottak (modell szinten)
Nyíl modell Szintén semmi megkötés Szintén semmi megkötés Célszerű ha tudja a saját forrását és célját Célszerű ha tudja a saját forrását és célját Forrás/cél objektumnak mindenképpen tudnia kell a nyilakról Forrás/cél objektumnak mindenképpen tudnia kell a nyilakról Navigálás a nyilakhoz a forrás/cél EditPartban Navigálás a nyilakhoz a forrás/cél EditPartban getModel(Source|Target)Connections() getModel(Source|Target)Connections()... protected List getModelSourceConnections() { return ((ElemModel)getModel()).getForrasNyilak(); } protected List getModelTargetConnections() { return ((ElemModel)getModel()).getCelNyilak(); }...
Nyíl nézet Draw2D PolylineConnection példány Draw2D PolylineConnection példány Figure leszármazott lehetnek gyerekei Figure leszármazott lehetnek gyerekei GEF-ben nincs nyíl hierarchia GEF-ben nincs nyíl hierarchia Mindegyik a teljes szerkesztőt kitöltheti Mindegyik a teljes szerkesztőt kitöltheti Speciális elemek Speciális elemek ConnectionAnchor: végpontok helye ConnectionAnchor: végpontok helye ConnectionRouter: nyíl alakja ConnectionRouter: nyíl alakja RotatableDecoration: végpontok „dísze” RotatableDecoration: végpontok „dísze”
ConnectionAnchor Nyíl két Anchor között megy Nyíl két Anchor között megy Forrás/cél EditPartok biztosítják Forrás/cél EditPartok biztosítják NodeEditPart interfészen deklarált metódusok NodeEditPart interfészen deklarált metódusok get(Source|Target)ConnectionAnchor() get(Source|Target)ConnectionAnchor() Két megvalósítás Két megvalósítás ChopboxAnchor: téglalap Figurehöz ChopboxAnchor: téglalap Figurehöz EllipseAnchor: ellipszis Figurehöz EllipseAnchor: ellipszis Figurehöz Egyéb esetben kell sajátot írni Egyéb esetben kell sajátot írni
ConnectionRouter A két Anchor közötti közbenső pontokat számolja ki A két Anchor közötti közbenső pontokat számolja ki ≈ LayoutManager, itt is lehet Constraint ≈ LayoutManager, itt is lehet Constraint Típusai Típusai NullRouter: egyenes vonal NullRouter: egyenes vonal BendpointConnectionRouter: töréspontok BendpointConnectionRouter: töréspontok Jövő: görbe nyilak támogatása Jövő: görbe nyilak támogatása
Nyíl nézet példa public class NyilView extends PolylineConnection { private Label lbl; public NyilView1() { lbl = new Label(); lbl.setOpaque(true); lbl.setBorder(new LineBorder()); add(lbl, new ConnectionLocator(this, ConnectionLocator.MIDDLE)); PolygonDecoration decors = new PolygonDecoration(); decors.setTemplate(PolygonDecoration.TRIANGLE_TIP); setTargetDecoration(decors); setConnectionRouter(new BendpointConnectionRouter()); } public setTorespontok(List tplista) { setRoutingConstraint(tplista); } }
Nyíl megjelenítés problémák Töréspontok elmásznak zoom esetén Töréspontok elmásznak zoom esetén Minden nyíl mindig látható Minden nyíl mindig látható
Nyíl EditPart Ősosztály: AbstractConnectionEditPart Ősosztály: AbstractConnectionEditPart Mindent tud, amit a többi EditPart Mindent tud, amit a többi EditPart Nyíl nézet létrehozása: createFigure() Nyíl nézet létrehozása: createFigure() Mindenképpen egy PolylineConnection kell Mindenképpen egy PolylineConnection kell Forrás és cél EditPartok lekérdezhetők Forrás és cél EditPartok lekérdezhetők getSource() és getTarget() függvények getSource() és getTarget() függvények Létrehozás közben nem feltétlenül elérhető! Létrehozás közben nem feltétlenül elérhető! Szerepelnie kell az EditPartFactoryban is Szerepelnie kell az EditPartFactoryban is
Nyíl szerkesztés Speciális nyíl EditPolicyk Speciális nyíl EditPolicyk ConnectionEditPolicy: törlés ConnectionEditPolicy: törlés ConnectionEndpointEditPolicy: kijelölés ConnectionEndpointEditPolicy: kijelölés Mindeképpen telepíteni kell a kijelöléshez Mindeképpen telepíteni kell a kijelöléshez BendpointEditPolicy: töréspontok módosítása BendpointEditPolicy: töréspontok módosítása Csak akkor, ha BendpointConnectionRouter van Csak akkor, ha BendpointConnectionRouter van
Nyíl létrehozás GraphicalNodeEditPolicy GraphicalNodeEditPolicy Nem a nyíl EditParthoz, hanem a forrás/cél elemek EditPartjához tartozik! Nem a nyíl EditParthoz, hanem a forrás/cél elemek EditPartjához tartozik! Két lépcsős létrehozás Két lépcsős létrehozás 1. getConnectionCreateCommand() 1. getConnectionCreateCommand() Request Command (ez nem hajtódik végre) Request Command (ez nem hajtódik végre) 2. getConnectionCompleteCommand() 2. getConnectionCompleteCommand() Request + első Command végső Command Request + első Command végső Command Csak ez hajtódik végre! Csak ez hajtódik végre!
Mit kell nekünk megírni III. Nyíl modell kód, értesítéssel Nyíl modell kód, értesítéssel Nyíl források/célok modelljében el kell tudni érni az onnan induló/oda érkező nyilakat! Nyíl források/célok modelljében el kell tudni érni az onnan induló/oda érkező nyilakat! Nyíl nézet osztályok Nyíl nézet osztályok Nyíl EditPart osztályok Nyíl EditPart osztályok Modell megjelenítés Modell megjelenítés createFigure(), refreshVisuals() createFigure(), refreshVisuals() Modell változás figyelés Modell változás figyelés activate(), deactivate() activate(), deactivate()
Mit kell nekünk megírni IV. Nyíl szerkesztő Commandok Nyíl szerkesztő Commandok Nyíl saját EditPolicyk Nyíl saját EditPolicyk Törlés, töréspontok módosítása,... Törlés, töréspontok módosítása,... Nyíl létrehozás EditPolicy Nyíl létrehozás EditPolicy Forrás/cél EditParthoz tartozik Forrás/cél EditParthoz tartozik GraphicalNodeEditPolicy GraphicalNodeEditPolicy Két lépcsős Két lépcsős Cél EditParté az első lépés! Cél EditParté az első lépés!
További funkciók Modell tulajdonságok szerkesztése az Eclipse Properties nézetében Modell tulajdonságok szerkesztése az Eclipse Properties nézetében Szövegek (címkék) szerkesztése közvetlenül a rajzon (direct editing) Szövegek (címkék) szerkesztése közvetlenül a rajzon (direct editing) Nagyítási lehetőség Nagyítási lehetőség Különálló fa modellnézet Különálló fa modellnézet Rajzok nyomtatása (Draw2D segítségével) Rajzok nyomtatása (Draw2D segítségével) Vonalzó, automatikus igazítás Vonalzó, automatikus igazítás
További információk Hivatalos GEF oldal Hivatalos GEF oldal eclipsewiki.editme.com/GefDescription eclipsewiki.editme.com/GefDescription eclipsewiki.editme.com/GefDescription felületes, de legalább angol leírás felületes, de legalább angol leírás www13.plala.or.jp/observe/#gef www13.plala.or.jp/observe/#gef www13.plala.or.jp/observe/#gef japán, de a forráskódok követhetők japán, de a forráskódok követhetők 2.x-es Eclipse/GEFhez, azóta kicsit változott 2.x-es Eclipse/GEFhez, azóta kicsit változott